102

在 C++11emplace_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));

或者这里的举动完全是多余的,还是没有效果?

4

2 回答 2

132

让我们看看您提供的不同调用的作用:

  1. emplace_back(mystring):这是新元素的就地构造,无论您提供什么参数。由于您提供了一个左值,因此该就地构造实际上是一个复制构造,即这与调用相同push_back(mystring)

  2. push_back(std::move(mystring)):这称为移动插入,在这种情况下std::string是就地移动构造。

  3. emplace_back(std::move(mystring)):这又是您提供的参数的就地构造。由于该参数是一个右值,它调用 的移动构造函数std::string,即它是一个就地移动构造,就像在 2 中一样。

换句话说,如果使用 T 类型的一个参数调用,无论是右值还是左值,emplace_back都是push_back等价的。

但是,对于任何其他参数,emplace_back赢得比赛,例如在 achar const*中使用 a vector<string>

  1. emplace_back("foo")要求std::string(char const*)就地施工。

  2. push_back("foo")首先必须调用std::string(char const*)匹配函数签名所需的隐式转换,然后像上面的案例 2 一样进行移动插入。因此它等价于push_back(string("foo"))

于 2014-11-11T09:27:05.623 回答
1

emplace_back 获取一个右值引用列表,并尝试直接就地构造一个容器元素。您可以使用容器元素构造函数支持的所有类型调用 emplace_back。当为非右值引用的参数调用 emplace_back 时,它会“回退”到普通引用,并且当参数和容器元素属于同一类型时,至少会调用复制构造函数。在您的情况下,'myvector.emplace_back(mystring)' 应该复制字符串,因为编译器无法知道参数 myvector 是可移动的。所以插入 std::move 什么给你想要的好处。对于已经构建的元素, push_back 应该和 emplace_back 一样工作。

于 2014-11-11T09:55:00.083 回答