我对以下语句的第 2 行和第 3 行中发生的事情感到困惑。据我了解
line2 ( vector<A> vec2(vec1);
) :对于存储在 vec1 中的每个 A 实例,将调用一个复制构造函数并将其存储在 vec2 中。令我困惑的是,即使我没有指定自定义复制构造函数,默认复制构造函数也会创建 A 的实例,可能会调用 A 和 B 的默认构造函数,但是然后,实际上正确地将 A 的成员数组的原始值初始化为拷贝和 A 的成员变量 b 的 vector 的值到拷贝的 B 的 vector 。那就是免费的深度复制。这是正确的吗?
line3 ( vector<A> vec3 = vec2;
) :不是调用复制构造函数,而是通过默认构造函数创建 A 的实例,然后调用存储实例的赋值运算符来初始化它。在这里,我再次获得免费的深度复制。
1. vector<A> vec1;
2. vector<A> vec2(vec1);
3. vector<A> vec3 = vec2;
其中 A 的定义如下所示。
class B
{
public:
vector<int> db;
};
class A
{
public:
char data[5];
int x;
B bee;
};
这里是证明深度复制正在发生的主要方法
int main()
{
A a, b;
a.data = {'a','b','c','d','\0'};
a.x = 1;
a.bee.db.push_back(99);
a.bee.db.push_back(100);
b.data = {'z','x','y','w','\0'};
b.x = 2;
b.bee.db.push_back(1);
b.bee.db.push_back(2);
vector<A> vec;
vec.push_back(a);
vec.push_back(b);
map<int, std::vector<A>> map1;
vector<A> vec1(vec);
map1[1] = vec1;
std::vector<A> vec2 = map1[1];
cout << vec2[0].data<< endl;
cout << vec2[0].bee.db[0] << endl;
vec2[0].x = 77777;
vec2[0].data = {'c','o','p','y','\0'};
cout << "vec1[0].x: " << vec1[0].x << endl;
cout << "vec1[0].data: " << vec1[0].data << endl;
return 0;
}
最佳答案
首先,std::vector
的所有拷贝和赋值都是深拷贝,
至少在 C++11 之前。 (在 C++11 中,还有一些版本
涉及移动语义。)
其次,您的评价:
`std::vector<A> vec3 = vec2;
不是很正确。因为vec2
的类型是一样的
作为被初始化的变量,这完全像
你的情况 2.(如果类型不同,正式地,
将调用一个转换构造函数来转换权利
hand side 到正确的类型,然后是复制构造函数
会被使用。但是允许编译器优化
复制。)
还有:如果你写过:
std::vector<A> vec3;
vec3 = vec2;
编译器会默认构造一个空的vec3
,然后
分配它。但作业仍会调用拷贝
每个 A
的构造函数(而不是赋值运算符)
对象,因为没有任何构造的 A
对象
vec3
当你做赋值时(赋值只能是
一个完全构造的对象)。
最后:关于深拷贝:std::vector
拷贝为
正如它所知道的那样深,这是包含的元素。然后,
包含的元素有责任更深入
(或不)。默认的复制构造函数将做一个成员
成员拷贝(所以如果所有包含的元素都有拷贝
构造函数,你是安全的),但是如果有例如原始指针,
您可能必须自己编写,才能为对象提供拷贝
你想要的语义。
关于C++ vector 构造函数和赋值问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17793773/