C + + Those details--copy constructor __jquery

Source: Internet
Author: User
Tags shallow copy volatile

About C + + copy constructor, has been not very clear, so obsessive-compulsive disorder and attack, must understand it.

Also attached is a reference article (this great God has written so well that I instantly understand the problem that has been tangled for a long time):

http://blog.csdn.net/lwbeyond/article/details/6202256/


I. Introduction:

The copy constructor, also called the copy constructor, is a special constructor that is called by the compiler to accomplish the construction and initialization of some other object based on the same class. Its only formal parameter must be a reference, but it is not limited to const, and generally the const limit is added. This function is often used to pass and return the value of a user-defined type at the time of a function call. Copy constructors call the copy constructors and member functions of the base class. If it can, it will be called in a constant way, or it can be called in a very different way.


two. Automatically generate copy constructors:

C++test.cpp: Defines the entry point for a console application.
//

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;

Class Copytest
{
private:
	string name;
	int id;
Public:
	copytest (int i, string n): ID (i), name (n)
	{
		cout<< "construct!" <<endl;
	}

	~copytest ()
	{
		cout<< "destruct!" <<endl;
	}

	void Display ()
	{
		cout<<name<< "" <<id<<endl;
	}
};


int _tmain (int argc, _tchar* argv[])
{
	copytest T1 (1, "T1");
	Copytest t2 = t1;
	T2. Display ();

	System ("pause");
	return 0;
}
The results are as follows:

construct!
T1 1
Please press any key to continue ...


Q&a

1. Hey. Here the wood has written the legendary copy constructor. Why did you implement the copy?

The reason is that if we don't write, the compiler will automatically generate a copy constructor for us (like constructors and destructors, if not written, the compiler will automatically generate for us).

2. So why would we write a copy constructor if it was generated for us?

Because automatically generated copy constructors can only make shallow copies and cannot make deep copies. About shallow copies and deep copies are specifically written below. Simply put, the system comes with some data types can be copied, and some complex, pointers, etc., can not be copied, so that automatically generated copy constructors will not meet our requirements, so we have to write a copy of the constructor.


three. Our own copy constructor: Free is not necessarily suitable for us, so we still have to write a copy of the constructor, in order to better achieve the required functionality. Look at what the real copy constructor looks like:

C++test.cpp: Defines the entry point for a console application.
//

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;

Class Copytest
{
private:
	string name;
	int id;
Public:
	copytest (int i, string n): ID (i), name (n)
	{
		cout<< "construct!" <<endl;
	}

	~copytest ()
	{
		cout<< "destruct!" <<endl;
	}

	Copy constructor
	copytest (const copytest& e)
	{
		name = E.name;
		id = e.id;
		cout<< "Copy construct!" <<endl;
	}

	void Display ()
	{
		cout<<name<< "" <<id<<endl;
	}
};


int _tmain (int argc, _tchar* argv[])
{
	copytest T1 (1, "T1");
	Copytest t2 = t1;//or copytest t2 (t1);
	T2. Display ();

	System ("pause");
	return 0;
}
Result: construct!
Copy construct!
T1 1
Please press any key to continue ...
Visible, the system calls the copy constructor we write.
Several points to note about copy constructors: 1. Copy constructors are a special constructor, which must be the same as the type name, and the argument must be a reference of this type (after adding other items, the system is not tuned for this function). 2. We generally write this parameter reference as a constant reference, because we do not want to copy the original object changes ... However, the const is not mandatory, such as the addition of a counting variable god horse function, or may need to change.
Four. When will the copy constructor be invokedThis is also a key issue, we just write the copy constructor, but we do not directly adjust the function, generally we are doing several operations, the automatic invocation of the copy constructor. A total of three cases: 1. When an object is initialized through another object, 2. When the parameter is passed by a value of 3. When the value is returned by a value method. Here are three different things to look at:
1. When an object is initialized through another objectThis is one of the best ways to understand how to create an object by copying the various properties of another object directly. This literally makes us think of calling the copy constructor. For example:
Copytest t2 = t1;
or copytest T2 (t1);
You can generate a new object by copying it by assigning it to it, or by calling it directly as a copy constructor, by passing a reference of an object to the copy constructor.

2. The second is the way in which the copy constructor is invoked when an object is passed as a parameter by means of a value passFor example:
C++test.cpp: Defines the entry point for a console application.
//

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;

Class Copytest
{
private:
	string name;
	int id;
Public:
	copytest (int i, string n): ID (i), name (n)
	{
		cout<< "construct!" <<endl;
	}

	~copytest ()
	{
		cout<< "destruct!" <<endl;
	}

	Copy constructor
	Copytest (copytest& e)
	{
		name = E.name;
		id = e.id;
		cout<< "Copy construct!" <<endl;
	}

	void Display ()
	{
		cout<<name<< "" <<id<<endl;
	}
};


function
void Passbyvalue (copytest e)
{
	cout<< "function is called!" passed the parameter by value delivery method <<endl;
}

int _tmain (int argc, _tchar* argv[])
{
	copytest T1 (1, "T1");
	Passbyvalue (t1);

	System ("pause");
	return 0;
}
Result: construct!
Copy construct!
Function is called!
destruct!
Please press any key to continue ...
Visible, we do not have an obvious object assignment operation, but we still invoke the copy constructor. And, in this, we didn't use the arguments we passed in, but the copy constructor was still invoked, that is, a temporary object was generated, and the temporary object was destructor after the function call was completed.
Let's analyze this process, when the object is passed by value, the operation in the function does not affect the original object, which means that during the value passing process, the object being manipulated in the function is not the same object as the object being passed in. Instead, an object is generated by copying the constructor. This process is similar to: Copytest T2 (T1), the parameter we pass in is T1, and the object T2 is generated from the copy constructor, which is the same as the T1 property field, but not the same object. This temporary object is destroyed when the operation is complete.
3. When an object is returned in the form of a valueWhen we return an object from a function and are passed by value, the copy constructor is invoked: for example:
C++test.cpp: Defines the entry point for a console application.
//

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;

Class Copytest
{
private:
	string name;
	int id;
Public:
	copytest (int i, string n): ID (i), name (n)
	{
		cout<< "construct!" <<endl;
	}

	~copytest ()
	{
		cout<< "No" <<id<< "<<" destruct! " <<endl;
	}

	Copy constructor
	Copytest (copytest& e)
	{
		name = E.name;
		In order to better distinguish which is the original object which is copied from the object, here do a little bit of hands and feet, copy ID will be +1
		id = e.id + 1;
		cout<< "Copy construct!" <<endl;
	}

	void Display ()
	{
		cout<<name<< "" <<id<<endl;
	}
};

Value-Passing method returns
Copytest Returnbyvalue ()
{
	copytest t (1, "Test")
	from the function; return t;
}

int _tmain (int argc, _tchar* argv[])
{
	 returnbyvalue ();

	System ("pause");
	return 0;
}

Result: construct!
Copy construct!
No1 destruct!
No2 destruct!
Please press any key to continue ...

(Note: Here in order to be able to distinguish which is copied, which is the original, the copy of the constructor to do a bit of the hands and feet, copy, copy the object id+1 A simple analysis of this process: Create a temporary object T,id to 1, and then to return this object, call the copy constructor, Generates a temporary object, T1, similar to copytest T1 (t), and generates an object of T1,id 2. When the function scope is out, we find that the original Object ID 1 was first refactored before the T1 of the temporary object generated by the copy constructor of the destructor.
Five. Right value reference and transfer semantics:If we declare an object and then follow this function directly, then the destructor of this temporary object is not invoked. What's going on here. is the legendary right value reference and transfer semantics. The right value is a temporary object, the object that is about to be destroyed, if we do not use the right value, we will re-create an object, call the copy constructor, and so on a lot of things, and then destroy the temporary object, but we use the right value, directly using the transfer semantics, without recreating the object, Also do not destroy the original object, directly equivalent to the new object pointer to the original object to be destroyed, so that greatly improve the efficiency. Under the split line, the function return value is assigned to an existing object if it is not declared. It is visible that the temporary object is destroyed. This does not occur because it is an assignment, not an initialization object.
//c++test.cpp: Defines the entry point for a console application.

#include "stdafx.h" #include <iostream> #include <string> using namespace std;
	Class Copytest {private:string name;
int id; public:copytest (int i, string n): ID (i), name (n) {cout<< "construct!"
	<<endl; } ~copytest () {cout<< "No" <<id<< "<<" destruct! "
	<<endl;
		}//Copy constructor Copytest (copytest& e) {name = E.name; id = e.id + 1;//in order to better distinguish which is the original object, here do a little bit of hands and feet, copied objects id+1 cout<< "Copy construct!"
	<<endl;
	} void Display () {cout<<name<< "" <<id<<endl;


}
}; function void Passbyvalue (Copytest e) {cout<< "function is called!" passed the parameter by value delivery method
<<endl;
	}//Value delivery method returns Copytest Returnbyvalue () {copytest T (1, "test") from the function;
return t;
	int _tmain (int argc, _tchar* argv[]) {copytest t = returnbyvalue ();
	 cout<< "--------------------------------------" <<endl;


	t = Returnbyvalue ();
	System ("pause");
return 0; }

construct!
Copy construct!
No1 destruct!
--------------------------------------
construct!
Copy construct!
No1 destruct!
No2 destruct!
Please press any key to continue ...


Six. Deep copy and shallow copy

1. Shallow copyLet's take a look at an example where we said that automatically generated copy constructors are not necessarily useful, and this example is the best proof:
C++test.cpp: Defines the entry point for a console application.
//

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;


Class Copytest
{
private:
	string name;
	int id;
	int* pointer;
Public:
	copytest (int i, string n): ID (i), name (n)
	{
		pointer = new int (1);
		cout<< "construct!" <<endl;
	}

	~copytest ()
	{
		delete pointer;
		cout<< "No" <<id<< "" << "destruct!" <<endl;
	}

	void Display ()
	{
		cout<<name<< "" <<id<<endl;
	}
};

After the void TestFunc ()
{
	//function finishes, the destructor
	copytest T1 (1, "Test") is performed;
	Copytest T2 (t1);
}

int _tmain (int argc, _tchar* argv[])
{
	testfunc ();
	System ("pause");
	return 0;
}

The result: Well, it collapsed ...


Why would it collapse? We analyze: The compiler generated for our copy of the constructor can only be shallow copy, the so-called shallow copy, is simply to the object of the data members of the simple assignment, and when the object contains dynamically generated members, we still blindly assign the value is not correct.
The above program for shallow copy, the pointer is also a simple assignment of pointer = E.pointer, and the position the pointer points to is the same ... So, when the first object is destroyed, the memory that the pointer points to is freed, the second object pointer the same position as the first, then the second object uses the pointer for the problem ... Inside this, we delete the object again, so it collapses ...
2. Deep copyWhat we want is not this, but the effect of the following picture:
This picture is the deep copy we want, so we need to reapply a piece of memory, then let the pointer of the copied object point to that location, and assign the value of the position to the same as the original object.
C++test.cpp: Defines the entry point for a console application.
//

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;


Class Copytest
{
private:
	string name;
	int id;
	int* pointer;
Public:
	copytest (int i, string n): ID (i), name (n)
	{
		pointer = new int (1);
		cout<< "construct!" <<endl;
	}

	~copytest ()
	{
		delete pointer;
		cout<< "No" <<id<< "" << "destruct!" <<endl;
	}

	Copy constructor
	Copytest (copytest& e)
	{
		name = E.name;
		id = e.id + 1;//to make it easy to differentiate, the copy constructor is made a little bit of a hand, and the copied dongdong id+1
		pointer = new int ();//Reassign a chunk of memory
		*pointer = * (e.pointer);// Assign the memory to the same value as the original object
		cout<< "Copy construct!" <<endl;
	}

	void Display ()
	{
		cout<<name<< "" <<id<<endl;
	}
};

After the void TestFunc ()
{
	//function finishes, the destructor
	copytest T1 (1, "Test") is performed;
	Copytest T2 (t1);
}

int _tmain (int argc, _tchar* argv[])
{
	testfunc ();
	System ("pause");
	return 0;
}

Result: construct!
Copy construct!
No2 destruct!
No1 destruct!
Please press any key to continue ...

Well, that's not going to collapse. We achieved a deep copy.
To sum up: the so-called shallow copy is no brain copy the value of the object, if there are dynamic members such as pointers, then the shallow copy of the problem. Deep copy Otherwise, the deep copy will apply a separate memory when it encounters the pointer, and then point to it with the pointer, so there is no problem.



Seven. Prevent passing by valueThrough the above analysis, we find that the copy constructor is invoked if the parameter is passed by value or returned. So, let's think about it another way, if you want to not let the pass by value happen, that is, to limit the occurrence of the argument by value, that is, to restrict the copy constructor. If we do not write, the system will give us a copy of the constructor, then we write a, to define it as a private, it is OK ... Holy. It's so witty ...
C++test.cpp: Defines the entry point for a console application.
//

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;


Class Copytest
{
private:
	string name;
	int id;
	int* pointer;
	Private copy constructor
	Copytest (copytest& e);
Public:
	copytest (int i, string n): ID (i), name (n)
	{
		pointer = new int (1);
		cout<< "construct!" <<endl;
	}

	~copytest ()
	{
		delete pointer;
		cout<< "No" <<id<< "" << "destruct!" <<endl;
	}

	void Display ()
	{
		cout<<name<< "" <<id<<endl;
	}
};

After the void TestFunc ()
{
	//function finishes, the destructor
	copytest T1 (1, "Test") is performed;
	Copytest T2 (t1);
}

int _tmain (int argc, _tchar* argv[])
{
	testfunc ();
	System ("pause");
	return 0;
}

So, we compile:
Well, the compiler error is the most easily found, more convenient than the Run-time debugging ....


Eight. Several areas of attention:1. Which of the following functions is a copy constructor, and why?

X::X (const x&);      
X::x (X);      
X::x (x&, int a=1);      
X::x (x&, int a=1, int b=2);  


Answer: For a class X, if the first parameter of a constructor is one of the following:
A) x&
b) Const x&
c) Volatile x&
d) Const volatile x&
And there are no other parameters or other parameters that have default values, then this function is a copy constructor.

X::X (const x&);  is the copy constructor      
x::x (X&, int=1);//is the copy constructor     
x::x (x&, int a=1, int b=2);/Of course, copy constructors  

2. Can there be more than one copy constructor in a class?
Answer: There can be more than one copy constructor in a class.


Class X {public   
:         
  X (const x&);      Const Copy Construction  
  X (x&);            Non-const copy construction  
};  



Note that if there is only one copy constructor in a class that has a parameter of x&, then copy initialization cannot be carried out using either const x or volatile X objects.


Class X {public      
:  
  x ();      
  X (x&);  
};      
  
Const X CX;      
x x = cx;    Error  

If a copy constructor is not defined in a class, the compiler automatically produces a default copy constructor.
This default parameter may be either x::x (const x&) or x::x (x&), which is determined by the compiler according to the context.















Related Article

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.