为什么复制构造函数被调用两次?

时间:2021-03-02 10:19:50

标签: c++ copy-constructor

我有以下代码片段

#include <iostream>
#include <vector> 

class Move {
    private:
        int* data;
         
    public: 
        void set_data_value(int d) {
            *data = d; 
        }
        int get_data_value(){
            return *data; 
        }

        Move(int d);
        Move(const Move &source);
        ~Move();
};

Move::Move(int d) {
    std::cout << "ctor being called" << std::endl; 
    data = new int; 
    *data = d; 
}

Move::Move(const Move& source) {
    std::cout << "copy ctor being called" << std::endl;
    data = new int; 
    *data = *source.data;
}

Move::~Move() {
    std::cout << "deleting Move" << std::endl; 
    delete data; 
}
int main() {
    Move x{1};
    
    Move y{x}; 

    std::vector<Move> vec; 
    vec.push_back(x);
    vec.push_back(y);

    return 1; 

}

输出如下:

ctor being called
copy ctor being called
copy ctor being called
copy ctor being called
copy ctor being called
deleting Move
deleting Move
deleting Move
deleting Move
deleting Move

我的问题是:当我只看到 3 个副本时,为什么要调用 4 次复制构造函数? (1 个来自 Move y{x},2 个来自两个 push_back() 调用)

2 个答案:

答案 0 :(得分:6)

您错过了计算向量的重新分配。将此行添加到您的代码中:

int main() {
    Move x{1};
    
    Move y{x}; 

    std::vector<Move> vec; 
    std::cout << "capacity: " << vec.capacity() << "\n";
    vec.push_back(x);
    std::cout << "capacity: " << vec.capacity() << "\n";
    vec.push_back(y);
    std::cout << "capacity: " << vec.capacity() << "\n";

    return 1; 

}

那么可能的输出是:

ctor being called
copy ctor being called
capacity: 0
copy ctor being called
capacity: 1
copy ctor being called
copy ctor being called
deleting Move
capacity: 2
deleting Move
deleting Move
deleting Move
deleting Move

vector 的容量从 0 开始,然后根据需要增加(常见的因子为 2 或 3)。可以看到,当容量从 1 增加到 2 时,会调用复制构造函数,将向量中已经存在的元素复制到内存中的其他位置。

注意上面的输出可以不同。分配策略需要进行细微的优化。它要求 push_back 具有摊销不变的复杂性,这意味着容量不能线性增长。虽然因子不一定是2。某些实现使用 3 或其他因素。

答案 1 :(得分:2)

这是由于每次数组不再足够时向量增加容量 您可以通过保留一些空间来防止这种情况 reserve()

https://en.cppreference.com/w/cpp/container/vector/reserve

相关问题