【问题标题】:Efficiency of C++11 push_back() with std::move versus emplace_back() for already constructed objects使用 std::move 与 emplace_back() 对已构造对象的 C++11 push_back() 效率
【发布时间】:2015-01-07 18:10:28
【问题描述】:

在 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));

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

【问题讨论】:

标签: c++11 move-semantics push-back emplace


【解决方案1】:

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

  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_backpush_back 都是等价的。

但是,对于任何其他参数,emplace_back 赢得比赛,例如 char const*vector&lt;string&gt; 中:

  1. emplace_back("foo") 调用std::string(char const*) 进行就地施工。

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

【讨论】:

  • 移动构造函数通常比复制构造函数更有效,因此尽管语义相同,但使用右值(情况 2、3)比使用左值(情况 1)更有效。
  • 这种情况怎么办? void foo(string&& s) { vector.emplace(s); // 1 个向量.emplace(std::move(s)); // 2 }
  • @VALOD 这些又是我列表中的数字 1 和 3。 s 可以定义为仅绑定到右值的右值引用,但在foo 内部,s 是一个左值。
【解决方案2】:

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

【讨论】:

  • 这是一种……描述转发/通用引用的有趣方式。
猜你喜欢
  • 2014-01-03
  • 2019-05-22
  • 1970-01-01
  • 2022-12-23
  • 2015-11-21
  • 2014-05-24
  • 1970-01-01
  • 2015-01-15
  • 1970-01-01
相关资源
最近更新 更多