复制语义,深复制(C++)

Copy semantic, Deep copy (C++)

我对 c++ 中的复制语义有疑问

这是我的代码

#include <iostream>

class DeepCopy
{
private:
    int *_myInt;

public:
    DeepCopy(int val)
    {
        _myInt = (int *)malloc(sizeof(int));
        *_myInt = val;
        std::cout << "resource allocated at address " << _myInt << std::endl;
    }
    ~DeepCopy()
    {
        free(_myInt);
        std::cout << "resource freed at address " << _myInt << std::endl;
    }
    DeepCopy(DeepCopy &source)
    {
        _myInt = (int *)malloc(sizeof(int)); // line 1 
        *_myInt = *source._myInt;  // line 2
        std::cout << "resource allocated at address " << _myInt << " with _myInt = " << *_myInt << std::endl;
    }
    DeepCopy &operator=(DeepCopy &source)
    {
        _myInt = (int *)malloc(sizeof(int));
        std::cout << "resource allocated at address " << _myInt << " with _myInt=" << *_myInt << std::endl;
        *_myInt = *source._myInt;
        return *this;
    }
    void printOwnAddress() { std::cout << "Own address on the stack is " << this << std::endl; }
    void printMemberAddress() { std::cout << "Managing memory block on the heap at " << _myInt << std::endl << std::endl; }

};

int main()
{
    DeepCopy source(42);
    source.printOwnAddress();
    source.printMemberAddress();
    DeepCopy dest1(source);
    dest1.printOwnAddress();
    dest1.printMemberAddress();

    source.printOwnAddress();
    source.printMemberAddress();
    return 0;
}

真正的结果在终端:

resource allocated at address 0x2511c20
Own address on the stack is 0x7ffdf539da00
Managing memory block on the heap at 0x2511c20

resource allocated at address 0x2512050 with _myInt = 42
Own address on the stack is 0x7ffdf539da10
Managing memory block on the heap at 0x2512050

Own address on the stack is 0x7ffdf539da00
Managing memory block on the heap at 0x2511c20

resource freed at address 0x2512050
resource freed at address 0x2511c20

来看看DeepCopy(DeepCopy &source)

据我了解,

  1. 第1行,为_myInt获取新内存,

  2. line 2, allocate the source's _myInt at the memory which obtained line 1

所以,我期待这样的结果

resource allocated at address 0x2511c20
Own address on the stack is 0x7ffdf539da00
Managing memory block on the heap at 0x2511c20

resource allocated at address 0x2512020 with _myInt = 42
Own address on the stack is 0x7ffdf539da10
Managing memory block on the heap at 0x2512020

Own address on the stack is 0x7ffdf539da00
Managing memory block on the heap at 0x2512050

resource freed at address 0x2512020
resource freed at address 0x2511c50

因为函数DeepCopy(DeepCopy &source)改变了源的成员地址,而不是目标的

但是,与上面的真实结果不同

我误会了什么?

source._myInt指向0x2511c20,复制前复制后。那不会改变。 dest1._myInt指向0x2512050,复制前后。那两个指针不会改变,也不应该改变。

存储在这些内存位置的数据被复制,但指针本身没有被复制。

画出来给大家看可能更容易理解:

首先创建 source 对象:

DeepCopy source(42);

它创建了这样的东西:

+---------------+     +----------------+
| source._myInt | --> | 42 @ 0x2511c20 |
+---------------+     +----------------+

然后创建 dest1 对象:

DeepCopy dest1(source);

如果我们一步一步地遍历我们首先拥有的复制构造函数

_myInt = (int *)malloc(sizeof(int)); // line 1 

这会让你拥有

+--------------+     +----------------+
| dest1._myInt | --> | ?? @ 0x2512050 |
+--------------+     +----------------+

[值此时不确定]

然后你有的复制:

*_myInt = *source._myInt;  // line 2

现在你有

+--------------+     +----------------+
| dest1._myInt | --> | 42 @ 0x2512050 |
+--------------+     +----------------+

我们终于回到了 main 函数,您有:

+---------------+     +----------------+
| source._myInt | --> | 42 @ 0x2511c20 |
+---------------+     +----------------+

+--------------+     +----------------+
| dest1._myInt | --> | 42 @ 0x2512050 |
+--------------+     +----------------+

你有两个不同的对象,每个都有自己不同的 _myInt 变量,每个都指向不同的内存位置。这些位置的值恰好相同,但指向这些值的指针不同。