我做这个工作主要是因为情况的发展。在 C++11 之前,只有:
vector<T>::push_back(const T&);
随着rvalue引用的引入,我建议增加以下重载:
vector<T>::push_back(T&&);
改变原始签名为以下内容:
template <class U> vector<T>::push_back(U&&);
这个决定的一部分是由于对向后兼容性的担忧(无论是否有必要),以及为了缓解厂商和委员会其他成员的担忧,即这只是一个功能的简单添加,而不是对现有功能的更改。
如果我今天从头重新设计vector
,我会认真考虑只使用:
template <class U> vector<T>::push_back(U&&);
或许只是这样:
template <class ...Args> vector<T>::emplace_back(Args&& ...)
您可能想要了解更多详细信息,请参见N1858。
为什么不按值push_back
?
此问题已被标记为重复:
为什么C++11 std容器具有按引用传递和按rvalue插入/推送方法?
该问题询问此问题。 所以我认为在这个答案中实际上需要解决这个方面是一件礼貌的事情...
对于左值和x值,与按引用解决方案相比,push_back(T)
将花费额外的移动构造。 x值需要2次移动构造,而左值需要1次复制构造和1次移动构造。
相反,使用当前设计,左值成本为1次复制构造,而x值成本为1次移动构造。
对于某些类型T
,移动构造并不便宜。 对于vector<T>
假设T
总是可以廉价移动的设计选择是不合适的。 例如,如果T
是std::array<double,100>
怎么办?更改为按值设计将需要2个复制构造而不是1个来push_back
(除prvalue外)。
按值的解决方案确实具有优点,并且应该在某些时候使用。只是vector<T> :: push_back()
不是这些时候之一。
push_back
的转发引用版本只是被称为emplace_back
。 - Barryemplace_back
接受转发引用作为元素类型的构造函数的参数。 - template boypush_back(T&&)
也将其参数移动到元素类型的构造函数中。 - BarryT
是向量的元素类型,但emplace_back
接受Args&&... args
并将args...
转发到构造函数,就好像通过element_type(std :: forward <Args> (args)...)
一样。而push_back
不会这样做。 - template boyvalue_type
具有复制构造函数,则可以使用emplace_back
作为push_back
的更一般版本。 - juanchopanza