C++11 C+的效率+;11对于已构建的对象,使用std::move与emplace_back()推送_back()
在C++11中,C++11 C+的效率+;11对于已构建的对象,使用std::move与emplace_back()推送_back(),c++11,move-semantics,push-back,emplace,C++11,Move Semantics,Push Back,Emplace,在C++11中,emplace_back()通常比push_back()更受欢迎(在效率方面),因为它允许就地构造,但是在对已构造的对象使用push_back(std::move())时仍然是这样吗? 例如,emplace\u back()在以下情况下仍然首选吗 std::string mystring(“hello world”); std::vector myvector; myvector.emplace_back(mystring); myvector.push_back(std::mo
emplace_back()
通常比push_back()
更受欢迎(在效率方面),因为它允许就地构造,但是在对已构造的对象使用push_back(std::move())
时仍然是这样吗?
例如,emplace\u back()
在以下情况下仍然首选吗
std::string mystring(“hello world”);
std::vector myvector;
myvector.emplace_back(mystring);
myvector.push_back(std::move(mystring));
//(当然,假设我们不关心使用mystring after的值)
此外,在上述示例中,执行以下操作是否有任何好处:
myvector.emplace_back(std::move(mystring));
或者在这里移动是完全多余的,还是没有效果?让我们看看您提供的不同调用的作用:
emplace\u back(mystring)
:这是新元素的就地构造,包含您提供的任何参数。由于您提供了一个左值,该就地构造实际上是一个副本构造,即,这与调用push\u-back(mystring)
push_-back(std::move(mystring))
:这将调用移动插入,在std::string
的情况下,它是一个就地移动构造
emplace\u back(std::move(mystring))
:这也是一个带有您提供的参数的就地构造。因为该参数是一个右值,所以它调用std::string
的move构造函数,也就是说,它是一个如图2所示的就地move构造
emplace\u back
和push\u back
都是等效的
但是,对于任何其他参数,emplace\u back
赢得比赛,例如,在向量中使用char const*
:
emplace\u back(“foo”)
调用std::string(char const*)
进行就地构造
push_back(“foo”)
首先必须调用std::string(char const*)
进行匹配函数签名所需的隐式转换,然后像案例2那样进行移动插入。在上面因此,它相当于push_back(字符串(“foo”))
emplace_back获取一个右值引用列表,并尝试直接就地构造容器元素。您可以使用容器元素构造函数支持的所有类型调用emplace_。
当为非右值引用的参数调用emplace_时,它会“退回”到正常引用,并且当参数和容器元素属于同一类型时,至少会调用复制构造函数ist。
在您的例子中,“myvector.emplace_back(mystring)”应该复制字符串,因为编译器无法知道参数myvector是可移动的。因此,插入std::move,以获得所需的好处。
对于已经构建的元素,push-back应该和emplace-back一样有效。myvector.emplace-back(mystring)代码>复制并且不移动。其他两个移动和应该是等效的。另请参见此问题和结果:这是一种描述转发/通用引用的有趣方式。移动构造函数通常比复制构造函数更有效,因此使用右值(案例2,3)比使用左值(案例1)更有效尽管语义相同,但这种情况如何?void foo(string&&s){vector.emplace(s);//1 vector.emplace(std::move(s));//2}@VALOD这些都是我列表中的数字1和3s
可以定义为仅绑定到右值的右值引用,但在foo
内部,s
是左值。