Вы совершенно ошиблись - The idea of shallow copy
. На самом деле, c++
не имеет ничего, что называется deep copy
, встроенного в себя. Итак, вызов чего-то shallow copy
- это a bit wrong
. И просто использование этих слов shallow copy
также создает множество confusion
.
Теперь позвольте мне объяснить, что происходит, когда cpp
выполняет initialization using assignment
. cpp
или c
(при копировании структуры) имеет концепцию, называемую bitwise copy
. В этой концепции all the member variables of one object(struct object/class object - you can say either) is identically copied to another object
. Теперь это totally wrong idea
, both objects point to same memory location
. Фактически, both object
имеет свои own memory location
и, конечно же, their variables
занимает different memory spaces
. Для вас я написал несколько тестов на память. Вы бы прекрасно поняли, если бы вы просто увидели тест и его результат:
#include <iostream>
#include <string.h>
using namespace std;
class Dummy {
int a, b;
int *p;
public:
Dummy() {
p = new int;
}
void setData(int x, int y, int z) {
a = x;
b = y;
*p = z;
}
void showData() {
cout << "a = " << a << " b = " << b;
cout << " p = " << *p << endl;
cout << endl; // an extra new line for readability of output
}
void showMemory() {
cout << "addr(a) = " << &a << " addr(b) = " << &b;
cout << " addr(p) = " << &p << endl;
}
~Dummy() {
*p = 100;
delete p;
}
};
// testing memory
void memoryTest() {
cout << "testing d1:" << endl;
Dummy d1;
d1.setData(3, 4, 5);
cout << "addr(d1) = " << &d1 << endl;
d1.showMemory();
cout << endl ;
cout << "testing d2:" << endl;
Dummy d2 = d1;
cout << "addr(d2) = " << &d2 << endl;
d2.showMemory();
}
int main() {
// memoryTest
memoryTest();
return 0;
}
А результат теста был:
testing d1:
addr(d1) = 0x6dfed4
addr(a) = 0x6dfed4 addr(b) = 0x6dfed8 addr(p) = 0x6dfedc
testing d2:
addr(d2) = 0x6dfec8
addr(a) = 0x6dfec8 addr(b) = 0x6dfecc addr(p) = 0x6dfed0
Это ясно показывает, что память, занятая эти два объекта d1
и d2
совершенно разные.
Теперь у вас может остаться еще один вопрос:
Тогда почему, когда я пишу *p=8
, это влияет как на d1
, так и на d2
? :
Когда вы назначаете Dummy d2 = d1;
, мы можем сказать, что произошло что-то, как показано ниже (хотя на самом деле этого не происходит, когда применяется побитовое копирование, это просто для ясности):
d2.p = d1.p
Итак, мы знаем, что d1.p
и d2.p
содержат одну и ту же ячейку памяти (примечание: d1.p является указателем. Поэтому он не содержит целого числа, а содержит адрес памяти типа int).
Итак, когда вы напишите *p = 8
, вы сообщаете программе go в ячейку памяти, на которую указывает p, и изменяете значение этой ячейки памяти на 8. (обратите внимание, здесь вы не меняли содержимое d1.p
, d1.p
по-прежнему содержит ту же ячейку памяти. Скорее, вы просто изменили содержимое этой ячейки памяти с 5 на 8). Вот почему при вызове d2.p
вы получаете измененное значение. причина, d2.p
содержит ту же ячейку памяти, что и d1.p
.
Теперь может возникнуть еще один вопрос:
Почему ваш код вылетает при освобождении p
в деструкторе? :
Теперь позвольте мне сначала спросить вас, можно ли вы освобождаете память то, что уже освобождено. Вы можете написать код, но поведение не определено. Это может привести к сбою вашей программы или ничего не делать.
Ну, в Dummy
destructor
вы написали delete p;
. Теперь сначала будет уничтожено либо d2
, либо d1
. Предположим, d2
уничтожено first
. Итак, когда вызывается d2's
разрушитель, p
это freed
. Затем будет вызван d1's
разрушитель, который также попытается free p
. Но p
уже освобожден. И в вашем случае программа встречает cra sh по этой причине.
Надеюсь, теперь вам все ясно.
Если что-то не понятно по поводу того, что я описал выше , а потом задавайте вопросы, я тоже постараюсь на них ответить.