C + +:: Shallow copy, deep copy, reference count copy, write-time copy __c++

Source: Internet
Author: User
Tags shallow copy
"Under what circumstances will a copy constructor in C + + be used: "

1 to construct another new object with existing objects of the same kind

2 when the formal parameter of a function is the object of the class, this function is called, the copy of the value is used, and the copy constructor is called
3 when the return value of the function is the object of the class, when the function is called, the object copy of the function is constructed with a temporary object and passed to the return of the function "Shallow copy": (Bit copy (value copy))

1, the concept: the so-called shallow copy is when the object is replicated, only the data members of the object of the copy, where the default copy of the constructor is also a shallow copy. In most cases, there is no problem with shallow copies, but when dynamic members appear, the problem occurs.

2, on the use of shallow copy examples:

#include <iostream>
using namespace std;
Class Test
{public
:
	//constructor
	test (int a)
		: _a (a)
	{}
	//copy constructor test
	(const test & x)
	{
		_a = x._a;
	}

Private:
	int _a;
};
int main ()
{
	Test b;
	Test C (b);
	return 0;
}

3, the defect of shallow copy:

Shallow copies are not feasible for pointer members. Multiple objects share the same block of space, the same memory address, but when you call the destructor to free space, the destructor is called multiple times, the space is freed many times, and the program crashes. "Copy of Reference count":

1, (how to introduce) concept: Because of the defects of shallow copy, so at this time we introduced the reference count of the copy.

Description: A copy of a reference count is used to solve a problem with a shallow copy, so it is also a shallow copy

2, how to achieve: we add a reference count Pcount for each memory character array, that is, when the constructor application space for more than 4 bytes. Indicates how many objects use this memory, how many objects to use, let the Pcount value plus 1, when the object is destructor, let the Pcount value minus 1, when the Pcount value is 0, the memory is released. Of course Pcount also want to implement memory sharing, so it is also a heap of data, each object has a pointer to it.

3, "description": But at this time, Pcount type of selection, will have to consider.

1 if the int type is selected: (Not taken)

#include <iostream> using namespace std;
			Class String {public://constructor string (const char* ptr = "") {if (ptr = NULL) {_ptr = new char[1];
			_pcount = 1;
		*_ptr = ' n ';
			else {_pcount = 1;
			_ptr = new Char[strlen (PTR) +1];
		strcpy (_PTR,PTR);
	}//Copy constructor String (string& s): _ptr (S._ptr), _pcount (s._pcount) {_pcount++; }//Assignment operator overload string& operator= (const string& s) {if (this!= &s) {if (--_pcount = 0) {Delete
				[] _ptr;
			Delete _pcount;
				else {_ptr = s._ptr;
				_pcount = S._pcount;
			(_pcount) + +;
	} return *this;
			}//destructor ~string () {if ((0 =--_pcount) && _ptr!= NULL) {delete[]_ptr;
			Delete _pcount;
		_ptr = NULL; 
			}//Overload [] char& operator[] (size_t size) {if (--_pcount >1) {char* ptemp = new Char[strlen (_ptr) +1];
			int pcount = 1;
			strcpy (PTEMP,_PTR);
			_pcount--;
			_ptr = ptemp; 
		_pcount = Pcount; return _ptr[size];
	} private:char*_ptr;
int _pcount;

};
	void Funtest () {String S1 ("Hello");
	String S2 (S1);
	String S3 (S2);
s3 = S2;
	int main () {funtest ();
return 0; }
Debugging:



(Note here I'm going to break the breakpoint to S2, intended to illustrate the problem): Originally increased s2, the two object count should be the same, but now one is 1, one is 2, not synchronized, we learned that the two objects of the count variable address is not the same. Indicates that this pcount is public and can be accessed concurrently by multiple objects.

2 If a static type is selected: (Not taken)

#include <iostream> using namespace std;
			Class String {public://constructor string (const char* ptr = "") {if (ptr = NULL) {_ptr = new char[1];
			_pcount = 1;
		*_ptr = ' n ';
			else {_pcount = 1;
			_ptr = new Char[strlen (PTR) +1];
		strcpy (_PTR,PTR);  }//Copy constructor String (string& s): _ptr (s._ptr) {_pcount++; Because it's static, it's possible to add value directly to the count.}//Assignment operator overload string& operator= (const string& s) {if (this!= &s) {if (--_pc
				Ount = = 0) {delete[] _ptr;
			Delete _pcount;
				else {_ptr = s._ptr;
				_pcount = S._pcount;
			(_pcount) + +;
	} return *this;
			}//destructor ~string () {if ((0 =--_pcount) && _ptr!= NULL) {delete[]_ptr;
			Delete _pcount;
		_ptr = NULL; 
			}//Overload [] char& operator[] (size_t size) {if (--_pcount >1) {char* ptemp = new Char[strlen (_ptr) +1];
			int pcount = 1;
			strcpy (PTEMP,_PTR);
			_pcount--;
			_ptr = ptemp; 
		_pcount = Pcount; Return _ptr[siZe];
	} private:char*_ptr;
static int _pcount;
};
int string::_pcount = 0;
	void Funtest () {String S1 ("Hello");
	String S2 (S1);
	String S3 (S2);
	s3 = S2;
	String S4 ("World");
String S5 (S4);
	int main () {funtest ();
return 0; }
Debugging:

First go to the S3, and then go to the S4, with S4 to construct S5, the result is wrong, go to the S4, the counter has become 1, indicating that these 5 objects common one pcount, can not implement reference count

3 so we think: If an object first time to open space to store strings and then open a new space to hold the new amount reference count, when it copies the construction of other objects so that the reference count of other objects to the same space to store reference count, Pcount set to int* on it, But this approach is flawed. (Readers can do it by themselves)

Defect One: Every time new two block space, create multiple objects when the efficiency is low

Defect Two: It allocates small pieces of space multiple times, it is easy to cause memory fragmentation, resulting in the allocation of large chunks of memory

4, Code implementation: (so I posted the optimized version of the code, in fact, is modeled after the bottom of the implementation of new, open up a space, but its first few bytes for counting)

#include <iostream>
using namespace std;
Class String
{public
:
	string (char *ptr = "")
	{
		if (ptr = NULL)
		{
			_ptr = new Char[strlen ( PTR) +5];
			_ptr = new Char[5];
			* (_ptr+4) = ' I ';
		}
		else
		{
			_ptr = new Char[strlen (PTR) +5];
			* ((int*) _ptr) = 1;
			_ptr + 4;
			strcpy (_ptr,ptr);
		}
	String (const string& s)
		: _ptr (s._ptr)
	{
		(* (int*) (_ptr-4)) + +;
	}
	string& operator= (const string& s)
	{
		if (this!= &s)
		{
			if (* (* (int*) (_ptr-4))) = = 0) c30/>{
				delete[]_ptr;
			}
			else
			{
				_ptr = s._ptr;
				+ + (* (int*) (_ptr-4))
			;
		}
		return *this;
	}
	~string ()
	{
		if (_ptr!= NULL) && ((--(* (int*) (_ptr-4))) = = 0))
		{
			delete[]_ptr;
			_ptr = NULL;
		}
	}
Private:
	char* _ptr;
void Funtest ()
{
	String s1 ("Hello");
	String S2 (S1);
	String S3 (S2); 
	s3 = s2;
}
int main ()
{
	funtest ();
	return 0;
}
"Deep Copy": (Address copy)

1, Concept: To take in the heap to apply for new space to access data, so that the data is independent of each other. Address copy.

2. Example: (copy constructor in string class)

String (const string& s)
	{
		_ptr = new Char[strlen (s._ptr) +1];
		strcpy (_ptr,s._ptr);
	}

"Write-time copy":

1, (how to introduce) concept: But when one of the objects changes its value, the value of other objects will change, so at this time we take this approach is to write-time copy.

2, the core idea:

(Copy on Write) if more than one caller requires the same resource (such as memory or data storage on disk), together, they get the same resources that the same pointer points to, until a certain caller attempts to modify the contents of the resource before the system actually copies a private copy to the caller. The original resources that other callers see remain unchanged. This process is transparent to the other callers. Advantage of the procedure : If the caller does not modify the resource, there will be no replicas created, so multiple callers can share the same resource only when reading operations

(write-time copy) refers to the use of a shallow copy of the method of copying other objects, multiple pointers to the same space, only when one of the objects modified to open a new space for the object, and its original point to the same space does not receive an impact.

3, Practice: To change the value of the object to new a piece of memory, and then first of the reference to copy the character data into the new array of characters, which is the write-time copy. Note that the reference count of the previously pointed memory is also reduced by 1 (because it points to an array of characters in the new heap) and a new block of memory is renewed in the heap to hold the newly referenced count, while the reference count of the new character array is set to 1. Because at this point only one object (that is, the object that changed the value) is using this memory.

4, Code implementation:

#include <iostream> using namespace std;
			Class String {public://constructor string (const char* ptr = "") {if (ptr = NULL) {_ptr = new char[1];
			_pcount = new int (1);
		*_ptr = ' n ';
			else {_pcount = new int (1);
			_ptr = new Char[strlen (PTR) +1];
		strcpy (_PTR,PTR);
	}//Copy constructor String (string& s): _ptr (S._ptr), _pcount (S._pcount) {(*_pcount) + +; }//Assignment operator overload string& operator= (const string& s) {if (this!= &s) {if (--(*_pcount) = = 0) {del
				Ete[] _ptr;
			Delete _pcount;
				else {_ptr = s._ptr;
				_pcount = S._pcount;
			(*_pcount) + +;
	} return *this;
			}//destructor ~string () {if (0 =-(*_pcount) && _ptr!= NULL) {delete[]_ptr;
			Delete _pcount;
		_ptr = NULL; }//Overload [] char& operator[] (size_t size) {if (-(*_pcount) >1) {char* ptemp = new Char[strlen (_ptr) +
			1];
			int* pcount = new int (1);
			strcpy (PTEMP,_PTR);
			(*_pcount)--;
			_ptr = ptemp; _pcouNT = Pcount;
	return _ptr[size];
	} private:char*_ptr;
int* _pcount;

};
	void Funtest () {String S1 ("Hello");
	String S2 (S1);
	String S3 (S2);
	s3 = S2;
	String S4 (S1);
S1[0] = ' Y ';
	int main () {funtest ();
return 0; }

After debugging, the results are as follows:


"Note": Because more than one object uses this piece of memory, when modifying their own, it is equivalent to modify the others. Before you write to this storage unit, be sure that no one else is using it. If the reference count is greater than 1, the storage unit must be copied before it is written so that it does not affect others.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.