C++ STL Vector:Push_back参考

Pra*_*abu 10 c++ stl

从cpp文档中std::vector,我看到了:

void push_back ( const T& x );
Run Code Online (Sandbox Code Playgroud)

据我所知,push_back它复制了我传递的对象.但是,为什么签名const T& ?通过查看这个,我最初认为它需要const参考我推动的任何对象vector.

eca*_*mur 12

另一种选择是

void push_back(T x);
Run Code Online (Sandbox Code Playgroud)

也就是说,以x价值取胜.但是,这将(在C++ 03中)导致创建x(参数中的副本)的额外副本push_back.以x通过const引用避免了这一点.

让我们看一下v.push_back(T())按值进行的调用的堆栈:

v.push_back(T());                      // instance of T
void std::vector<T>::push_back(T x)    // copy of T
new (data_[size_ - 1]) T(x)            // copy of copy of T
Run Code Online (Sandbox Code Playgroud)

通过const参考我们得到:

v.push_back(T());                             // instance of T
void std::vector<T>::push_back(const T &x)    // const reference to T
new (data_[size_ - 1]) T(x)                   // copy of T
Run Code Online (Sandbox Code Playgroud)

在C++ 11中,有可能(尽管没有必要)x采用值并使用std::move它将它移动到向量上:

v.push_back(T());                             // instance of T
void std::vector<T>::push_back(T x)           // copy of T
new (data_[size_ - 1]) T(std::move(x))        // move the copy of T
Run Code Online (Sandbox Code Playgroud)


Jer*_*fin 8

只是为了澄清@ecatmur描述的"额外副本",如果push_back按值接收它的参数,那么你将从你的对象开始.该副本将push_back作为参数传递给它.然后,push_back将创建的副本投入的载体本身.

由于真正的实现push_back通过引用接收它的参数,it(push_back)直接在向量中创建新对象作为原始对象的副本.

如前所述,是的,使用移动语义的C++ 11,有可能(尽管可能不是特别有利)按值传递参数,然后将该参数中的值移动到向量中的新对象中.例如,如果你在向量中放入的是一个主要只包含一个指针和一些"簿记"字段(分配的内存量,当前使用的内存量)的字符串,那几乎和传递一个引用,因为一个移动只能做一个浅拷贝 - 复制指针和簿记自己的值,而不是它指向的所有数据.但是,如果有问题的对象直接保存了所有数据(即不是指针),那么移动就像复制一样慢.

通过引用传递,避免所有复制,所以即使对于类似字符串的东西,它通常也更快(对于这样的情况,原始对象不能被无效).它还具有使用C++ 98/03的次要优势,而不仅仅是C++ 11.


And*_*rew 7

object你推入参考,以避免传递extra copy.比副本放在vector.