1

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

#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 中所做的任何更改,即使在分配需要反映在两个对象上,因为它们指向相同的位置。但是在这个例子中,当我改变一个对象的值时,它不会反映在另一个对象中。使用用户定义的复制构造函数时获得相同的结果。

有人可以澄清这个话题,浅拷贝是否正在发生!

谢谢!

4

4 回答 4

3

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

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:您的示例中没有深/浅复制。对于值,这种区别没有意义。使用aint*来查看效果。

于 2019-04-24T08:38:53.603 回答
2

我在网上读到默认复制构造函数会“浅复制”

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

来自参考:

如果隐式声明的复制构造函数没有被删除,如果odr-used则由编译器定义(即生成并编译一个函数体)。对于联合类型,隐式定义的复制构造函数复制对象表示(如 std::memmove)。对于非联合类类型(类和结构),构造函数使用直接初始化按照初始化顺序对对象的基类和非静态成员执行完整的成员复制。

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

于 2019-04-24T08:48:38.753 回答
1

考虑浅拷贝到单纯的分配。所以,

Test t2 = t1; 

方法

t2.a = t1.a

sincea是一个int,如果你修改了a,from t1,它不会体现在t2。所以对于int浅拷贝来说确实是深拷贝。

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

于 2019-04-24T08:34:57.467 回答
0

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

T member(original.member);

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

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

于 2019-04-24T08:42:37.910 回答