从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)
只是为了澄清@ecatmur描述的"额外副本",如果push_back
按值接收它的参数,那么你将从你的对象开始.该副本将push_back
作为参数传递给它.然后,push_back
将创建的副本是投入的载体本身.
由于真正的实现push_back
通过引用接收它的参数,it(push_back
)直接在向量中创建新对象作为原始对象的副本.
如前所述,是的,使用移动语义的C++ 11,有可能(尽管可能不是特别有利)按值传递参数,然后将该参数中的值移动到向量中的新对象中.例如,如果你在向量中放入的是一个主要只包含一个指针和一些"簿记"字段(分配的内存量,当前使用的内存量)的字符串,那几乎和传递一个引用,因为一个移动只能做一个浅拷贝 - 复制指针和簿记自己的值,而不是它指向的所有数据.但是,如果有问题的对象直接保存了所有数据(即不是指针),那么移动就像复制一样慢.
通过引用传递,避免所有复制,所以即使对于类似字符串的东西,它通常也更快(对于这样的情况,原始对象不能被无效).它还具有使用C++ 98/03的次要优势,而不仅仅是C++ 11.