对于已经构造的对象,C + + 11 push_back()与 std: : move 相对于 emplace_back()的效率

在 C + + 11中,emplace_back()通常优于 push_back()(就效率而言) ,因为它允许就地构造,即 但是,当对一个已经构造好的对象使用 push_back(std::move())时,情况仍然是这样吗?

例如,在下列情况下,emplace_back()仍然是首选吗?

std::string mystring("hello world");
std::vector<std::string> myvector;


myvector.emplace_back(mystring);
myvector.push_back(std::move(mystring));
// (of course assuming we don't care about using the value of mystring after)

此外,在上面的例子中,是否有任何好处来代替:

myvector.emplace_back(std::move(mystring));

还是说这种做法完全是多余的,或者根本没有效果?

33103 次浏览

Let's see what the different calls that you provided do:

  1. emplace_back(mystring): This is an in-place construction of the new element with whatever argument you provided. Since you provided an lvalue, that in-place construction in fact is a copy-construction, i.e. this is the same as calling push_back(mystring)

  2. push_back(std::move(mystring)): This calls the move-insertion, which in the case of std::string is an in-place move-construction.

  3. emplace_back(std::move(mystring)): This is again an in-place construction with the arguments you provided. Since that argument is an rvalue, it calls the move-constructor of std::string, i.e. it is an in-place move-construction like in 2.

In other words, if called with one argument of type T, be it an rvalue or lvalue, emplace_back and push_back are equivalent.

However, for any other argument(s), emplace_back wins the race, for example with a char const* in a vector<string>:

  1. emplace_back("foo") calls std::string(char const*) for in-place-construction.

  2. push_back("foo") first has to call std::string(char const*) for the implicit conversion needed to match the function's signature, and then a move-insertion like case 2. above. Therefore it is equivalent to push_back(string("foo"))

The emplace_back gets a list of rvalue references and tries to construct a container element direct in place. You can call emplace_back with all types which the container element constructors supports. When call emplace_back for parameters which are not rvalue references, it 'falls back' to normal references and at least the copy constructor ist called when the parameter and the container elements are of the same type. In your case 'myvector.emplace_back(mystring)' should make a copy of the string becaus the compiler could not know that the parameter myvector is movable. So insert the std::move what gives you the desired benefit. The push_back should work as well as emplace_back for already constructed elements.