为什么 std::string 没有 emplace 或 emplace_back?

Why is there no emplace or emplace_back for std::string?

提问人:24n8 提问时间:3/5/2020 最后编辑:24n8 更新时间:3/5/2020 访问量:3402

问:

我很确定我以前在这里看到过这个问题,但是当我尝试搜索时,我似乎找不到该帖子,而且我不记得答案了。

为什么没有或为?emplaceemplace_backstd::string

我认为这与 的使用无关,因为您可以有一个字符向量,并且在向量中 ing 一个字符没有问题。charemplace_back

C++ 字符串 emplace

评论

2赞 alter_igel 3/5/2020
一些值得深思的东西:可以使用通用容器,与.请看这个 CppCon 演讲: youtube.com/watch?v=SDJImePyftYstd::basic_string<T>std::vector<T>
0赞 Jesper Juhl 3/5/2020
为(和朋友)编写和提交标准提案始终是一种选择。std::basic_stringemplace()emplace_back()
0赞 walnut 3/5/2020
@alterigel 该标准似乎只允许 的非数组 POD 类型,因此作为通用容器的使用非常有限,参见 timsong-cpp.github.io/cppwp/n4659/strings#general-1(和 timsong-cpp.github.io/cppwp/n4659/strings#basic.string-1)。std::basic_string

答:

8赞 Yksisarvinen 3/5/2020 #1

不会有任何收获push_back

它的力量在于它就地构造了一个对象,它被设计为停留在那里。无需复制或移动。它还为创建对象提供了更简单的语法,但这只是一个小优势。emplace_back

class Person
{
    std::string name;
    int age;
    double salary;
}

int main()
{
    std::vector<Person> people;
    people.push_back(Person{"Smith", 42, 10000.0}); //temporary object is needed, which is moved to storage
    people.emplace_back("Smith", 42, 10000.0); //no temporary object and concise syntax
}

对于(或任何只能容纳基元类型的理论容器),增益是不存在的。无论你是在原地构造对象,还是移动或复制对象,你都会在程序集级别执行相同的操作 - 在给定的内存中写入一些字节。
语法也不能变得比现在更简洁 - 没有需要调用的构造函数。您可以使用文字或其他变量,但您必须在两者中执行完全相同的操作,并且
std::stringpush_backemplace_back

int main()
{
    std::vector<char> letters;
    letters.push_back('a');
    letters.emplace_back('a'); //no difference
}

评论

3赞 Timo 3/5/2020
“只能容纳基元类型”我不认为标准禁止非原始类型。cppreference 说它必须是一个微不足道的类型,但这仍然是编译的,所以我不确定该怎么看。除了“类似字符的对象”之外,我在标准中找不到约束,它实际上并没有定义 afaik。
1赞 François Andrieux 3/5/2020
对于同质性来说,这仍然很好。如果您有一个通常与容器一起使用的函数模板,则无法使用或无法支持 。emplace_backstd::string
2赞 n314159 3/5/2020
@François我认为,在这里,多数人的需求超过了少数人的需求。当我们添加字符串时,许多人会开始使用它来获得虚构的收益,这会带来混乱和歧义。对于那些需要统一容器语法的少数人来说,1)如果push_backs可能的话,编写一个函数emplace并不难,如果有必要,可以编写一个函数emplace,2)这可能已经是必要的,因为有而不是。emplace_backsetemplaceemplace_back
2赞 Slava 3/5/2020
@n314159实际上根据 en.cppreference.com/w/cpp/string/basic_string,因为 C++17 必须满足需要存在的 SequenceContainer 概念,所以这对我来说似乎是一个缺陷std::stringemplace_back
1赞 n314159 3/5/2020
@Slava 在我看来,该标准只要求字符串是一个连续的容器,这反过来只会为其迭代器而不是其接口添加要求。
0赞 Paul Sanders 3/5/2020 #2

(例如)的优点是它直接在向量中构造一个 T 类型的对象,而不是构造一个临时的然后复制它。std::vector‹T>::emplace_back

由于是原始类型,一种方法与另一种方法相比没有优势,因此没有理由存在。charstd::string::emplace_back

评论

2赞 Slava 3/5/2020
存在有一个很大的理由——泛型编程的通用接口std::string::emplace_back