复制构造函数如何执行?

How does copy constructor execute?

本文关键字:执行 构造函数 何执行 复制      更新时间:2023-10-16

我正在尝试详细了解复制构造函数。在这样做的时候,我做了下面的例子,

#include<iostream>
class Test
{
private:
int a;
public:
/*
Test(const Test &t)                          // User defined copy constructor
{
a = t.a;
} */
Test()
{
a = 120;
}
int display()
{
return a ;
}
void set(int var)
{
a = var;
}
};
int main()
{
Test t1;
std::cout << "t1.a " << t1.display() << std::endl;
Test t2 = t1;                                           //Default copy constructor is called
std::cout << "T2.a " << t2.display() << std::endl;
t2.set(99);                                             //Changing the value
std::cout << "t1.a " << t1.display() << std::endl;
std::cout << "T2.a " << t2.display() << std::endl;
return 0;
}

我在网上读到默认复制构造函数做"浅拷贝"所以这意味着如果 obj1 = obj2,即使在赋值之后我在 obj1 或 obj2 中所做的任何更改 需要反映在两个对象上,因为它们指向同一位置。 但是在这个例子中,当我更改一个对象的值时,它不会反映在另一个对象中。使用用户定义的复制构造函数时,将获得相同的结果。

有人可以澄清这个话题吗,无论是否正在发生浅层复制!

谢谢!

浅拷贝不是你需要记住的特殊东西。相反,它只是由于使用引用或指针而发生的事情。康赛德这个例子:

struct foo { 
int* x;
};
int a = 4;
foo f{&a};

这里x指向a,如果您复制f新实例x将指向相同的a。这是一个浅层的副本。深拷贝就是要尊重不仅x,而且x所指向的东西,是foo不可分割的一部分,也需要复制。通常,编译器无法决定您想要什么。x只是一个参考,还是x所指的也是foo的一部分?因此,你得到的是显而易见的:只有成员被复制,而不是他们可能引用的内容。

现在,如果您复制foo,然后修改x指向的值,那么这将修改相同的a。制作了一个浅层副本。根据我的经验,深和浅复制这两个术语增加了混乱而不是清晰。您免费获得的是所有成员都被复制(无论是浅副本还是深副本)。只有当你需要更多(也复制脚尖)时,你才需要担心浅拷贝与深拷贝。

TL;DR:在你的例子中没有深/浅的副本。对于值,这种区别是没有意义的。使用int*查看效果。

我在网上读到默认复制构造函数做"浅拷贝">

这不是复制构造函数的正确思维方式。默认复制构造函数只是复制类型中的任何成员,就像依次对成员应用复制构造函数一样。

参考资料:

如果未删除隐式声明的复制构造函数,则它是 定义(即,生成和编译函数体)由 编译器(如果使用 ODR)。对于联合类型,隐式定义的副本 构造函数复制对象表示形式(如 std::memmove)。为 非联合类类型(类和结构),构造函数执行 对象基和非静态成员的完整成员副本,在 它们的初始化顺序,使用直接初始化。

所以它实际上更像是一个深拷贝,而不是一个浅拷贝。

考虑将浅拷贝仅仅赋值。所以

Test t2 = t1; 

方法

t2.a = t1.a

由于aint,如果修改a,从t1,就不会反映在t2中。 所以对于int浅拷贝确实是深拷贝。

考虑a属于int*型的情况。现在t2.at1.a都指向相同的内存位置。因此,如果您修改内存位置的值t1.a,同样会通过t2.a反映出来,因为它们实际上指向同一位置。

类的隐式定义复制构造函数只是复制每个成员 [class.copy.ctor]/14。复制成员基本上意味着新对象(被复制到的对象)的每个成员都是从被复制对象的相应成员初始化的,就像你写的那样

T member(original.member);

其中T是成员的类型,original是要复制的对象。如果member是类类型,这实际上归结为调用T的复制构造函数。但是,您的成员是普通int,这不是类类型。没有要调用的复制构造函数(int没有复制构造函数);新对象中的int只是从原始对象的int初始化的,归结为将原始int的值复制到新int中......

您的编译器无法区分深拷贝和浅拷贝,它甚至不知道"深拷贝"或"浅拷贝"应该是什么意思。在语言层面上,C++没有深拷贝或浅拷贝这样的东西。这些只是程序员常用的术语,用于讨论复制逻辑上(但不是物理上)包含其他对象的对象的不同方法......