Копировать семанти c, Глубокая копия (C ++) - PullRequest
0 голосов
/ 24 февраля 2020

У меня вопрос о копировании semanti 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. строка 2, выделите _myInt источника в памяти, которая получается строка 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) изменяет адрес члена источника, а не адресата

Однако, он отличается от приведенного выше реального результата.

Что я неправильно понял?

1 Ответ

1 голос
/ 24 февраля 2020

source._myInt указывает на 0x2511c20 до и после копирования. Это не меняет dest1._myInt указывает на 0x2512050 до и после копирования. Эти два указателя не изменяются и не должны изменяться.

Данные, хранящиеся в этих ячейках памяти, копируются, но сами указатели не копируются.

Возможно, легче понять, если мы рисуем это для вас:

Сначала вы создаете объект source:

DeepCopy source(42);

, который создает что-то вроде этого:

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

Затем вы создаете dest1 object:

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, каждая указывает на различные области памяти. Значение в этих местах оказывается одинаковым, но указатели на эти значения отличаются.

...