我有以下代码片段
#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()
调用)
答案 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()