copy constructor
Starting with the constructor, in C++ object-oriented design, each object represents an entity of an abstract collection, and each entity needs its own memory space in the current running process, that is, the object has space when it exists.To do this, C++ introduces constructors to instantiate objects and allows the compiler to request space for the object from the operating system so that it can exist in the operating system.
The copy constructor is a constructor that assigns one-to-one data members of the old object to the new data members of the object, that is, the result of the copy constructor is identical to the constructor, and new objects are generated.
View the following code:
#include <iostream> using namespace std; class A{ public: A(){ cout << "default constructor " << endl; } A(int a) {num=a;cout << "constructor with param" << endl; } A(const A &a) { num=a.num; cout << "copy constructor " << endl; } ~A(){ cout << "destructor " << this->num << endl; } void print() { cout << this->num << endl; } private: int num; }; void para_copy(A &a) { } int main() { A a(100); // overloaded constructor A a1=a; //copy constructor a1.print(); A c;//Default constructor return 0; }
The output is as follows:
constructor with param //a Overload Construction copy constructor //a1 copy construction 100 default constructor //c Default Construction destructor 0 //c Destruction destructor 100 //a1 Destruction destructor 100 //a Destruction
The copy constructor call scenario is as follows:
- As in the code above, one object is initialized by another object
- Object as function parameter
- Object as function return value
For the object as a function parameter and the copy constructor that is called when the value is returned, see the code below
The output is as follows#include <iostream> using namespace std; class A{ public: A(){ cout << "default constructor " << endl; } A(int a) {num=a;cout << "constructor with param" << endl; } A(const A &a) { num=a.num; cout << "copy constructor " << endl; } ~A(){ cout << "destructor " << this->num << endl; } void print() { cout << this->num << endl; } private: int num; }; void param_copy(A a) { cout << "param obj" << endl; } A return_value() { A d(0); cout << "return obj" << endl; return d; } int main() { A c; param_copy(c); return_value(); return 0; }
default constructor //c Default Construction copy constructor // Object as parameter, copy to temporary object param obj destructor 0 // Destruct Temporary Objects constructor with param //The d object in function return_value uses an overloaded constructor return obj destructor 0 //Destruct d object, local variable destructor 0 //Destruct c object
The description of deep and shallow copies is as follows:
-
Typically, the default-generated copy constructors and assignment operators simply copy the values.If the data members of a class have pointers, copying by value transfer alone will cause the member pointers of two objects to point to the same block of memory, and the same memory will be freed twice when two objects are destructed, causing the pointer to hang empty.
-
Deep copy is the second case above where the copy constructor uses deep copy when there is a pointer variable in the data member, that is, the address space of the initialization object is reassigned in the constructor.
The code is as follows:
#include <iostream> using namespace std; class A{ public: A(){ p=new int(10);cout << "default constructor " << endl; } //A(int a) {num=a;cout << "constructor with param" << endl; } A(const A &a) { num=a.num; p=new int(10); *p=*(a.p); cout << "copy constructor " << endl; } ~A(){ cout << "destructor " << this->num << endl; } void print() { if(p!=NULL) { delete p; cout << this->num << endl; } } private: int num; int *p; }; void param_copy(A a) { cout << "param obj" << endl; } int main() { A c; A b(c); return 0; }
Overloaded assignment operator
The biggest difference between assignment operators and copy constructors is that assignment operators do not generate new objects, while copy constructors generate new objects.
#include <iostream> using namespace std; class Person { public: Person(){} Person(const Person& p) { cout << "Copy Constructor" << endl; } Person& operator=(const Person& p) { cout << "Assign" << endl; return *this; } private: int age; string name; }; void f(Person p) { return; } Person f1() { Person p; return p; } int main() { Person p; Person p1 = p; // A cout <<" p1 addr " << &p1 << endl; Person p2; cout <<" p2 addr " << &p2 << endl; p2 = p; // B cout <<" p2 addr after asign " << &p2 << endl; f(p2); // C f Function Parameters cout <<" p2 addr after asign " << &p2 << endl; p2 = f1(); // If the return value of D f1 is a change of object, copy construction is performed first, and the returned object is assigned to p2 cout <<" p2 addr after asign " << &p2 << endl; Person p3 = f1(); // E Generates a new object, which is a copy constructor cout <<" p3 addr " << &p3 << endl; getchar(); return 0; }
The output is as follows:
Copy Constructor //A Assign //B Copy Constructor //C Copy Constructor //D Assign //D Copy Constructor //E