For the normal type, the copy is no big deal.
int a = 0;int B = A;
No problems will occur.
And the class object is different from ordinary object, the inner structure of class object is generally more complex, there are various member variables.
Shallow copy
First of all, we often encounter the case of shallow copies.
#include <stdio.h> class Student{public: student () //constructor, p points to a space allocated in the heap { _name = new char (100); printf ("default constructor \ n"); } ~student () //destructor, releasing the dynamically allocated space { if (_name! = NULL) { delete _name; _name = NULL; printf ("destructor \ n");} } Private: char * _name; A pointer member};int main () { student A; Student B (a); Copy object return 0;}
This code appears to be fine at first glance, by copying A to B through the class's default constructor, but the program crashes once it runs.
After my hard study and research, finally found that the problem lies.
Because my class does not have a copy constructor, it student b(a)
is called, and the compiler automatically generates a default copy constructor that completes a bit copy between objects. A bit copy is also called a shallow copy .
Shallow copy :
Shallow copy just copy the pointer, and do not create a new space, so that two pointers to the same address, so that at the end of the object block, call function destructor, will cause the same resource destruction 2 times, that is, delete the same piece of memory 2 times, resulting in a program crash.
A shallow copy causes A and B to point to the same piece of memory, and any change affects the other party.
Because A and B point to the same piece of memory space, when A is released, B points to the memory space no longer exists, so there will be a memory leak situation.
How to avoid shallow copy harm?
It is customary to develop custom copy constructors, and when the copy constructor is explicitly defined, the compiler invokes the copy constructor, and in order to avoid a program crash, use a custom copy constructor, and of course it is not impossible for us to write the code in the form of a shallow copy.
Deep copy
Use the custom copy constructor to complete the deep copy!!! Class A{public: A () //constructor, p points to a space allocated in the heap { m_pdata = new char (+); printf ("default constructor \ n"); } A (const a& R) //copy constructor { m_pdata = new char (+); Re-dynamically allocating space memcpy (M_pdata, R.m_pdata, strlen (R.m_pdata)) for new objects; printf ("copy constructor \ n"); } ~a () //destructor, releasing the dynamically allocated space { if (m_pdata! = NULL) { delete m_pdata; printf ("destructor \ n");} } Private: char *m_pdata; A pointer member};int main () { a A; A B (a); Copy object return 0;}
In the copy constructor, a new space is made for the B object, so that A and B point to different spaces, but the content is consistent but not mutually affected.
The repetition of the space and the release of space efficiency is very low, the wise people of the Earth decided to use the copy-on-write.
Write-time copy
Write-time copy: The introduction of a counter, each piece of different contents of the space is again composed of a counter, in the construction of the first class point, the counter is initialized to 1, and each time a new class also points to the same space, the counter plus 1, in the destruction of the space corresponding counter is 1, 1 is to perform cleanup work, The counter is greater than 1 minus 1. If there is a need to make additions and deletions and other operations, and then copy space to complete, conducive to improve efficiency.
Class String{public: string (const char* str = "") : _str (new Char[strlen (str) + 1 + 4])//+1 means that the string is followed by a ' + ', + 4 means to open up a space to hold the reference count { _str + = 4;//_str points to the data store strcpy (_STR, str); _getcount () = 1; } String (const string& s) : _str (s._str) { _getcount () + +; } string& operator= (string& s) { if (this! = &s) { if (--_getcount () = = 0) { Delete[] (_str-4); } ++s._getcount (); _str = S._str; } return *this; } ~string () { if (--_getcount () = 0) { delete[] (_str-4);//Note: Since the counter is stored at the address of the _STR first address-4, Therefore, in the destruction must be aware of the full release, to avoid memory leaks. } } Public: int& _getcount () { return * ((int*) _str-1); Private: char* _str;};
Related articles:
C # Shallow copy and deep copy instance parsing
Introduction to assignment, shallow copy, deep copy in Python