拷贝构造函数如何执行?

How does copy constructor execute?

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

#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;
}

我在网上看到默认复制构造函数 "shallow copy" 所以这意味着如果 obj1 = obj2,即使在赋值之后我在 obj1 或 obj2 中做了什么改变 需要反映在两个对象上,因为它们指向相同的位置。 但是在这个例子中,当我改变一个对象的值时,它并没有反映在另一个对象中。使用用户定义的复制构造函数时获得相同的结果。

谁能澄清一下这个话题,浅拷贝是否正在发生!

谢谢!

考虑浅拷贝到单纯的赋值。所以,

Test t2 = t1; 

表示

t2.a = t1.a

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

考虑案例 a 的类型 int*。现在 t2.at1.a 都指向相同的内存位置。因此,如果您修改内存位置 t1.a 处的值,相同的内容将通过 t2.a 反映出来,因为它们实际上指向相同的位置。

浅拷贝不是什么特殊的东西,你需要记住它作为规则。相反,它只是由于使用引用或指针而发生的事情。考虑这个例子:

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:您的示例中没有 deep/shallow 副本。对于价值观,这种区分没有意义。用一个int*看看效果。

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

T member(original.member);

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

你的编译器不区分深拷贝和浅拷贝,它甚至不知道 "deep copy" 或 "shallow copy" 是什么意思。在语言级别上,C++ 中没有深拷贝或浅拷贝之类的东西。这些只是程序员常用的简单术语,用于谈论复制 逻辑上(但不是物理上)包含其他对象的对象的不同方法......

I read online that default copy constructor does "shallow copy"

这不是拷贝构造函数的正确思路。默认的复制构造函数只是复制类型中的任何成员,就好像在成员上依次应用复制构造函数一样。

参考资料:

If the implicitly-declared copy constructor is not deleted, it is defined (that is, a function body is generated and compiled) by the compiler if odr-used. For union types, the implicitly-defined copy constructor copies the object representation (as by std::memmove). For non-union class types (class and struct), the constructor performs full member-wise copy of the object's bases and non-static members, in their initialization order, using direct initialization.

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