Basic concepts:
Deep copy:
When an object is copied to another object, the assigned object stores an extra copy of the assignment object. If a member of a class contains a pointer member and is initialized with new, the assigned member will apply for a piece of memory to copy the contents of the memory referred to by the pointer member of the assigned object into this block of memory. two pointers each point to their own requested memory .
Shallow copy:
Similar to deep copies, shallow copies are directly assigned to non-pointer members. But when a member of a class contains a pointer member and initializes it with new, the assigned member pointer does not request a single memory, but only the block of memory that points to the pointer member of the assignment object. Two pointers point to the same piece of memory.
When we do not define the copy constructors and assignment operators for the class, the compiler generates the default version, which uses a shallow copy .
Back to the above, why do we need to define "deep copy" of the copy constructor and assignment algorithm pinch? Is it because the default shallow copy causes an error?
That's right! We know that if you define a class that contains pointer members, if it will use new to request additional memory. In the destructor, we use Delete to release the corresponding memory footprint.
Consider two scenarios:
1. An object is initialized with another existing object , which invokes the default copy constructor (and may also call the assignment operator, depending on the compiler). Because a shallow copy is used, there is a case where the pointer members of the two objects point to the same memory, and when the two objects are discarded, their destructors are called. This occurs when the same block of memory is released two times and an unknown error occurs.
Similarly, if you define a function that returns an object , it also causes the same memory to be released two times, why? Because this will also invoke the copy constructor, passing by value means creating a copy of the original variable. The pointer to the object in the caller and this function (callee) points to the same memory. When the function returns, the object in the function is killed, the destructor is called, and the memory is freed ... Don't worry, none of this will tell you. Well, when the object in the caller is destructor, that memory is released once again ... is still an unpredictable error. Similarly, when you create a temporary object, you call the copy constructor, which will happen the same thing--the same strange error.
2. assignment between two existing objects , which invokes the default assignment operator function. The following situation is the same as 1, all of which are light copies--two objects with pointers to the same memory and then released two times.
"When a defined class contains a pointer member and is initialized by using regular new (or locating new, positioned in the requested heap memory), you need to define the copy constructor and assignment operator for the deep copy," or you will be taken by aliens. Icon:
code Example:
C + + Code//Light copy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21st 22 23 24 25 26 27 28 29 30 31
|
|
#include <iostream> #include <cstring> using namespace Std; Class Person { Char *pname; Public Person (char *PN) { cout << "Constructing" << PN << Endl; PName = new Char[strlen (PN) + 1]; if (pname!= 0) strcpy (PName, PN); } ~person () { cout << "Destructing" << pname << Endl; if (pname) delete []pname; PName = NULL; } }; int main () { Person P1 ("Tom"); Person P2 (p1); } |
C + + Code/deep copy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21st 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
|
#include <iostream> #include <cstring> using namespace Std; Class Person { Char *pname; Public Person (char *PN); Person (the const person &P); ~person (); }; Person::P Erson (char *pn) { cout << "Constructing" << PN << Endl; PName = new Char[strlen (PN) + 1]; if (pname!= 0) strcpy (pname, PN); } Person::P Erson (const person &P) { cout << "Copying" << p.pname << "\ n"; PName = new Char[strlen (p.pname) + 1]; if (pname!= 0) strcpy (pname, p.pname); } Person::~person () { cout << "Destructing" << pname << Endl; if (pname) delete []pname; PName = NULL; } void Main () { Person P1 ("Tom"); Person P2 (p1); } |