首页 > 解决方案 > 为什么复制构造函数被调用两次?

问题描述

我有以下代码片段

#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}两个push_back()调用)

标签: c++copy-constructor

解决方案


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

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

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

请注意,上面的输出可能会有所不同。分配策略受到微妙的优化。它要求push_back具有摊销常数复杂性,这意味着容量不能线性增长。虽然这个因素不一定2。一些实现使用3或不同的因素。


推荐阅读