12

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

void push_back ( const T& x );

我知道这push_back会复制我传递的对象。但是,为什么是签名const T& ?通过查看这个,我最初认为它需要const引用我推送到vector.

4

3 回答 3

15

另一种选择是

void push_back(T x);

x按价值取值。但是,这会(在 C++03 中)导致创建一个额外x的副本(在 的参数中的副本push_back)。通过constx引用可以避免这种情况。

让我们看一下按值调用的堆栈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
于 2012-08-01T15:28:19.723 回答
9

只是为了澄清@ecatmur 描述的“额外副本”,如果push_back按值接收它的参数,会发生什么事情是你将从你的对象开始。其副本将push_back作为其参数传递给。然后push_back将创建一个副本放入向量本身。

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

如前所述,是的,使用 C++11 使用移动语义,可以(尽管可能不是特别有利)按值传递参数,然后将值从该参数移动到向量中的新对象中。例如,如果您放入向量中的是一个字符串,该字符串主要包含一个指针和几个“簿记”字段(分配的内存量,当前使用的内存量),那几乎和传递一个引用,因为移动只能做一个浅拷贝——复制指针和簿记值本身,而不是它指向的所有数据。但是,如果所讨论的对象直接保存其所有数据(即,不是指针),那么移动将与复制一样慢。

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

于 2012-08-01T15:44:07.473 回答
8

object你 push 是通过引用传递的,以避免extra copy。比副本放置在vector.

于 2012-08-01T15:25:40.390 回答