C++STL矢量:引用Push_back

C++ STL Vector: Push_back taking reference

本文关键字:back Push 引用 矢量 C++STL      更新时间:2023-10-16

std::vector的cpp文档中,我看到了以下内容:

void push_back ( const T& x );

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

另一个选项是

void push_back(T x);

即取x的值。然而,这将(在C++03中)导致创建x的额外副本(push_back的参数中的副本)。通过常量引用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

通过常数参考我们得到:

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

您推送的object是通过引用传递的,以避免extra copy。然后在vector中放置一个副本。

为了澄清@ecatmur所描述的"额外副本",如果push_back按值接收其参数,则会发生从对象开始的情况。其副本将作为参数传递给push_back。然后push_back将创建的副本,将其放入向量本身。

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

如前所述,是的,使用移动语义的C++11,可以(尽管可能不是特别有利)按值传递参数,然后将该参数中的值移动到向量中的新对象中。如果你在向量中输入的是一个字符串,它主要只包含一个指针和几个"记账"字段(分配的内存量、当前使用的内存量),那么的效率几乎与传递引用的效率一样高,因为移动只能进行浅层复制——复制指针和记账值本身,而不是它指向的所有数据。然而,如果有问题的对象直接保存了它的所有数据(即,不是指针),那么移动将和复制一样慢。

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