我对以下陈述的第2行和第3行中发生的事情感到困惑。据我所知
line2(vector<A> vec2(vec1);
):对于存储在vec1内部的A的每个实例,将调用复制构造函数并将其存储在vec2中。令我困惑的是,即使我没有指定自定义复制构造函数,默认复制构造函数,也会创建一个A实例,可能调用A和B的默认构造函数,但是,实际上,正确地将A的成员数组的原始值初始化为副本和A的成员变量b的向量值到副本的B向量。这是免费的深度复制。这是对的吗?
line3(vector<A> vec3 = vec2;
):不是调用复制构造函数,而是默认构造函数创建A的实例,然后调用存储实例的assigment运算符来初始化它。在这里,我正在免费深度复制。
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;
}
答案 0 :(得分:4)
首先,std::vector
的所有副本和作业都是深拷贝,
至少预先C ++ 11。 (在C ++ 11中,还有一些版本
涉及移动语义。)
其次,您的评价:
`std::vector<A> vec3 = vec2;
不是很正确。因为vec2
的类型是相同的
正如初始化变量一样,这就像
你的情况2.(如果类型不同,正式,
将调用转换构造函数来转换右侧
手边到正确的类型,然后是复制构造函数
会被使用。但是编译器可以优化出来
副本。)
另外:如果你写了:
std::vector<A> vec3;
vec3 = vec2;
编译器将默认构造一个空vec3
,然后
分配它。但是作业仍然可以调用副本
每个A
的构造函数(而不是赋值运算符)
对象,因为没有任何构造的A
对象
当你完成任务时vec3
(并且任务只能是
一个完全构造的对象)。
最后:关于深层复制:std::vector
复制为
它知道的深处,哪些是包含的元素。然后,
更深层次的是所包含的要素的责任
(或不)。默认的复制构造函数将执行成员
成员副本(如果所有包含的元素都有副本
建设者,你是安全的,但如果有,例如原始指针,
您可能必须自己编写,为对象提供副本
你想要的语义。
答案 1 :(得分:3)
(1)将导致默认的构造向量(如您所知)。
(2)和(3)将分别产生来自vec1
和vec2
的复制构造的载体。
矢量复制构造函数将构造源矢量的每个元素复制到新矢量中。您可以从此副本实现中获得一个免费的浅表副本。对于您的特定对象A
和B
浅层和深层副本完全相同,因此您最终也可以使用深层副本。
答案 2 :(得分:0)
我认为它是浅薄的和深刻的复制概念。根据我的说法,它不会调用Default C'tor,即它会在两种情况下直接调用Default Copy C'tor,而By Default实现是一个浅层复制,因为它不会处理数据成员的内存分配(如果有的话)。 / p>