在std::vector
的cpp文档中,我看到了:
void push_back ( const T& x );
我知道push_back
会复制我传递的对象。但是,为什么签名const T& ?
通过查看此内容,我最初认为它需要const
引用我推送到vector
的任何对象。
答案 0 :(得分:12)
另一种选择是
void push_back(T x);
即按值x
。但是,这将(在C ++ 03中)导致创建x
的额外副本(push_back
的参数中的副本)。通过const引用取x
可以避免这种情况。
让我们看看按值获取的电话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
通过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
在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
答案 1 :(得分:8)
只是为了澄清“额外副本”@ecatmur所描述的,如果push_back
按值接收了它的参数,那么你将从你的对象开始。该副本将作为参数传递给push_back
。然后push_back
会创建的副本以放入矢量本身。
由于push_back
的实际实现通过引用接收其参数,因此它(push_back
)直接在向量中创建新对象作为原始对象的副本。
如前所述,是的,使用移动语义的C ++ 11,有可能(尽管可能不是特别有利)通过值传递参数,然后将该参数中的值移动到新的对象中向量。例如,如果你在向量中放置的是一个主要只包含一个指针和一些“簿记”字段(分配的内存量,当前使用的内存量)的字符串,那将是 与传递引用一样高效,因为移动只能执行浅拷贝 - 复制指针和簿记值本身,而不是它指向的所有数据。但是,如果有问题的对象直接保存了所有数据(即不是指针),那么移动就像复制一样慢。
通过引用传递,避免所有复制,因此即使像字符串这样的东西,它通常也更快(对于这样的情况,原始对象不能被无效)。它还具有使用C ++ 98/03的次要优势,而不仅仅是C ++ 11。
答案 2 :(得分:7)
您推送的object
通过引用传递以避免extra copy
。副本放在vector
。