矢量push_back不止一次调用copy_constructor?

Ana*_*dan 6 c++ stdvector

我对矢量push_back行为的方式有点困惑,使用下面的代码片段我预计复制构造函数只能被调用两次,但输出建议不然.是矢量内部重组导致这种行为.

输出:

Inside default

Inside copy with my_int = 0

Inside copy with my_int = 0

Inside copy with my_int = 1
Run Code Online (Sandbox Code Playgroud)
class Myint
{
private:
    int my_int;
public:
    Myint() : my_int(0) 
    {
        cout << "Inside default " << endl;
    }
    Myint(const Myint& x) : my_int(x.my_int)
    {
        cout << "Inside copy with my_int = " << x.my_int << endl;
    }

    void set(const int &x)
    {
        my_int = x;
    }
}

vector<Myint> myints;
Myint x;

myints.push_back(x);
x.set(1);
myints.push_back(x);
Run Code Online (Sandbox Code Playgroud)

Col*_*mbo 11

怎么了:

  1. x通过插入push_back.发生一个副本:使用参数初始化新创建的元素.my_int被取为零,因为xs默认构造函数初始化它.

  2. 第二个元素是push_back'd; 由于达到了内部容量,向量需要重新分配内存.
    由于没有为Myint1隐式定义移动构造函数,因此选择了复制构造函数; 第一元件被复制到新分配的存储器(其my_int仍然是零...这样的拷贝构造示出了my_int作为0再次),然后x被复制到初始化所述第二元件(与第一在步骤1).这时候x已经my_int设置为一个,这就是拷贝构造函数的输出告诉我们.

所以通话总数是三.这可能因实现而异,因为初始容量可能不同.但是,两次通话是最小的.

您可以提前预留更多内存来减少副本数量 - 即更高的向量容量,因此重新分配变得不必要:

myints.reserve(2); // Now two elements can be inserted without reallocation.
Run Code Online (Sandbox Code Playgroud)

此外,您可以在插入时删除副本,如下所示:

myints.emplace_back(0);
Run Code Online (Sandbox Code Playgroud)

这个"赋予"一个新元素 - emplace_back是一个可变参数模板,因此可以接受任意数量的参数,然后将其转发 - 无需复制或移动 - 到元素构造函数.

1因为有一个用户声明的复制构造函数.