为什么vector :: push_back有两个重载?

tem*_*boy 29 c++ c++11

为什么不vector::push_back采用转发引用而不是两次重载?我已经读过你想要在左值和右值上重载的唯一原因是你的函数是否为它们做了不同的事情,那么vector::push_back除了移动/复制之外,两个重载的不同之处是什么?

How*_*ant 50

我这样做主要是因为情况如何演变.在C++ 11之前,只有:

vector<T>::push_back(const T&);
Run Code Online (Sandbox Code Playgroud)

随着rvalue引用的引入,我建议添加重载:

vector<T>::push_back(T&&);
Run Code Online (Sandbox Code Playgroud)

而不是将原始签名更改为:

template <class U> vector<T>::push_back(U&&);
Run Code Online (Sandbox Code Playgroud)

做出这一决定的部分原因是由于对后向兼容性的担忧(无论是否保证),以及减轻供应商和委员会其他人的关注,这是对功能的简单补充,而不是对现有功能的更改.

如果我vector今天从头开始重新设计,我会认真考虑:

template <class U> vector<T>::push_back(U&&);
Run Code Online (Sandbox Code Playgroud)

或者只是:

template <class ...Args> vector<T>::emplace_back(Args&& ...);
Run Code Online (Sandbox Code Playgroud)

N1858中,您可能想了解的更多细节.

为什么不push_back按价值?

此问题已被标记为重复:

为什么C++ 11 std容器有pass-by-ref和pass-by-rvalue insert/push方法?

问这个问题.所以我认为在这个答案中真正解决这个方面是有礼貌的事情......

对于左值和左值,push_back(T)与副参考解决方案相比,将花费额外的移动结构.xvalues需要2个移动结构,而左值需要1个复制结构和1个移动结构.

相比之下,在目前的设计中,左值成本为1个复制结构,x值为1个移动结构.

对于某些类型T,移动施工并不便宜.vector<T>假设T总是便宜地移动它将是一个糟糕的设计选择.例如,如果Tstd::array<double, 100>?更改为按值设计需要2个复制结构而不是1个push_back(prvalues除外).

按值解决方案确实具有优势,并且应该使用它的时间.只是那vector<T>::push_back()不是那个时代之一.

  • `v.push_back({aggregate_initialization});`在你的"如果它今天设计的地方"下打破.完美转发并不完美. (5认同)
  • @amfcosta:第一点:我说_考虑_。我没有花时间测试和实施这些注意事项。第二点:不,左值将绑定到转发引用`U&amp;&amp;`,没有移动或复制。然后在内部代码将 `forward&lt;U&gt;(u)` 构造一个 `T`。假设 `U` 是一个 `T`,那就是 1 次复制构造。我可能还会限制 `U` 使得 `is_constructible&lt;T, U&gt;{}`。 (2认同)