类似的问题在这里和这里都有讨论,但我认为我们没有得到一个清晰的答案,因此我重新提出这个问题。
C++11标准有两种向vector中添加新元素的方法,它们是std::vector::push_back
和std::vector::emplace_back
。
它们之间的区别在于std::vector::emplace_back
会直接就地构造对象,而std::vector::push_back
则基本上是将对象(或原始类型)复制或移动到向量末尾。
因此,对于将原始类型添加到std::vector
中,std::vector::push_back
看起来是更好的选择。例如:
std::vector<int> vVec;
vVec.push_back(10);
int iVar 30;
vVec.push_back(iVar);
但是当我们谈论对象时,情况并不那么清晰。以std::string向量为例,如果我想添加一个字面字符串,我应该使用
std::vector::emplace_back
,而当我想复制或移动字符串对象时,我应该使用std::vector::push_back
吗?为了更清楚地说明我的问题,让我们看几个场景:
第一个场景:
std::vector<string> vVec;
std::string sTest("1st scenario");
vVec.push_back(sTest);
vVec.emplace_back(sTest);
push_back将sTest
的副本与vVec
末尾的新元素相关联,而emplace_back
在vVec
末尾创建字符串对象,并将sTest
的内容复制到其中。
在这种情况下,哪个更有效率或者无所谓?
第二种场景:
std::vector<string> vVec;
std::string sTest1("2st scenario");
std::string sTest2("2st scenario");
vVec.push_back(move(sTest1));
vVec.emplace_back(move(sTest2));
Push_back方法是具备移动语义的,但emplace_back
呢?在这种情况下哪个更有效率呢?
第三种情况:
std::vector<string> vVec;
std::string sTest("3st scenario");
vVec.push_back(sTest.substr(4,4));
vVec.emplace_back(sTest.substr(4,4));
由于std::string::substr返回另一个std::string,因此我们有了第二种情况的相同情况?
结论
如果std::vector::emplace_back比std::vector::push_back更高效,只有涉及字面值(原地构造)时才这样做,那么它真的可以被证明是可用的吗?如果可以,请给我一些例子。
需要注意的重要事项是,std::vector::emplace_back是在c++11中实现的,而不是在c++0x中实现的,因此我认为它存在的理由是充分的。
emplace_back
中呢?抱歉,但我发现您的示例更加混乱而不是清晰。据我所知,emplace_back
可以在推入实例之前为您节省构造实例的步骤,因此我认为您的比较并不公平。 - 463035818_is_not_a_numberemplace_back
,你不需要在容器外部构造实例,然后再将其推入。在大多数示例中,在将其插入向量之前确实会创建一个实例,因此我认为比较push_back
和emplace_back
对于这些情况是毫无意义的。 - 463035818_is_not_a_number