Before studying this chapter we have learned about the constructors and destructors of classes, and for ordinary types of objects, replication between them is simple, for example:
int a = 10;
int b =a;
The object of the class you define is also an object, and no one can prevent us from copying it in the following way, for Example:
#include <iostream>
usingnamespaceStd
classTest
{
public:
Test (intTemp
{
p1=temp;
}
protected:
intp1;
};
voidMain()
{
Test a (99);
Test b=a;
}
Ordinary objects and class objects are the same object, the characteristics of their similarities and differences, there are member variables inside the class object, and ordinary objects are not, when the same replication method occurs on different objects, then the system to their operation is not the same, in terms of class objects, The same type of class object is the copy constructor to complete the entire copy process, in the above code, we did not see the copy constructor, also completed the copy work, this is why? Because when a class does not have a custom copy constructor, the system automatically provides a default copy constructor to complete the copy Work.
below, to illustrate the situation, in the ordinary case (in The example above), we define a copy constructor that is the same as the system default copy constructor to see how it works inside!
The code is as Follows:
#include <iostream>
usingnamespaceStd
classTest
{
public:
Test (intTemp
{
p1=temp;
}
Test (test &c_t)//this is the custom copy constructor
{
cout<< "enter Copy constructor" <<endl;
p1=c_t.p1;//this sentence can not complete the copy work if it is removed, the core statement of this copy process
}
public:
intp1;
};
voidMain()
{
Test a (99);
Test b=a;
cout<<b.p1;
Cin. Get ();
}
The test (test &c_t) in the above code is our custom copy constructor, and the name of the copy constructor must be the same as the class name, and the formal parameter of the function is a reference variable of this type and must be a reference.
When you initialize another newly constructed object with a custom class type Object that has already been initialized, the copy constructor is automatically called . If you do not have a custom copy constructor, the system will provide a default copy constructor to complete the process, and the copy core statement of the above code is to copy the P1=C_T.P1 within the constructor using Test &c_t. If this code is removed, then the P1 property of the B object will be given an unknown random value;
2
Let's discuss the problem of shallow and deep copy.
In the case of the above code, many people will ask, since the system will automatically provide a default copy constructor to handle replication, then we have no meaning to customize the copy constructor ah, yes, in the ordinary case this is not necessary, but in a certain writing situation, Members of the class are required to open up a dynamic heap of memory, if we do not customize the copy constructor and let the system handle itself, then it will cause heap memory ownership confusion, imagine, has opened up a heap address originally belongs to object a, because the copy process occurs, B object obtained is a already opened heap address , once the program is generated, the heap is released, the computer is impossible to know who this address is really belong to, when the continuous occurrence of two times the destruction of a running Error.
For a more detailed explanation of the problem, see the Code BELOW.
#include <iostream>
usingnamespaceStd
classInternet
{
public:
Internet (Char*name,Char*address)
{
cout<< "load constructors" <<endl;
strcpy (internet::name,name);
strcpy (internet::address,address);
Cname=NewChar[strlen (name) +1];
if(cname!=null)
{
strcpy (internet::cname,name);
}
}
Internet (internet &temp)
{
cout<< "load Copy constructor" <<endl;
strcpy (internet::name,temp.name);
strcpy (internet::address,temp.address);
Cname=NewChar[strlen (name) +1];//note here, Deep copy of the embodiment!
if(cname!=null)
{
strcpy (internet::cname,name);
}
}
~internet ()
{
cout<< "load destructor!";
Delete[] cname;
Cin. Get ();
}
voidShow ();
protected:
Charname[20];
Charaddress[30];
Char*cname;
};
voidInternet::show ()
{
cout<<name<< ":" <<address<<cname<<endl;
}
voidTest (Internet Ts)
{
cout<< "load Test function" <<endl;
}
voidMain()
{
Internet a ("china software development laboratory", "www.cndev-lab.com");
Internet b=A
B.show ();
Test (b);
}
The above code demonstrates a deep copy of the problem, the CNAME attribute of object B to take a new way to open up memory to avoid the memory of the confusion caused by the destruction of free space error, I must mention, for the above program I do not explain a lot, is to hope that the reader itself to run the program to observe the changes, and then a deep understanding.
the definition of a copy and a shallow copy can be easily understood As: if a class has resources (heaps, or other system resources), the process can be called a deep copy when the object of the class has a copy process. The case where the object has resources but the replication process does not replicate the resources is considered a shallow copy .
In particular, it is important to note that a shallow copy of a resource can result in an ambiguous resource attribution when the resource is released, which causes the program to run in Error.
In our previous tutorial we discussed the problem of generating temporary variables from function return objects, so let's take a look at whether returning custom type objects in a function also follows this rule to produce temporary objects !
3
Run the following code first:
#include <iostream>
usingnamespaceStd
classInternet
{
public:
Internet ()
{
};
Internet (Char*name,Char*address)
{
cout<< "load constructors" <<endl;
strcpy (internet::name,name);
}
Internet (internet &temp)
{
cout<< "load Copy constructor" <<endl;
strcpy (internet::name,temp.name);
Cin. Get ();
}
~internet ()
{
cout<< "load destructor!";
Cin. Get ();
}
protected:
Charname[20];
Charaddress[20];
};
Internet TP ()
{
Internet b ("china Software development laboratory", "www.cndev-lab.com");
returnb
}
voidMain()
{
Internet a;
A=TP ();
}
From the above code running results can be seen, the program has loaded the destructor three times, proved that the function returned by the custom type object will also produce temporary variables, in fact, object A is the temporary Internet class type Object temp Value.
This look section we'll take a look at the nameless object .
initializing an object system with a nameless object does not call the copy Constructor.
So what's a nameless object?
Very simple, If there is in the main function of the program Above:
Internet ("china Software Development laboratory", "www.cndev-lab.com");
Such a statement produces a nameless object, the nameless object calls the constructor but initializes the object system with a nameless object without invoking the copy constructor!
The following three sections of code are the three examples of objects initialized with nameless Objects.
#include <iostream>
usingnamespaceStd
classInternet
{
public:
Internet (Char*name,Char*address)
{
cout<< "load constructors" <<endl;
strcpy (internet::name,name);
}
Internet (internet &temp)
{
cout<< "load Copy constructor" <<endl;
strcpy (internet::name,temp.name);
Cin. Get ();
}
~internet ()
{
cout<< "load destructor!";
}
public:
Charname[20];
Charaddress[20];
};
voidMain()
{
Internet a=internet ("china Software development lab", "www.cndev-lab.com");
cout<<a.name;
Cin. Get ();
}
The result of the above code is a little "unexpected", from the logic that when the Nameless object is created, it should call the custom copy constructor, or the default copy constructor to complete the copy process, but in fact the system does not do so, because the Nameless object after the use of the entire program has been lost in the role, For this scenario, C + + sees the code as:
Internet a ("china software development laboratory", www.cndev-lab.com);
The process of creating a nameless object is omitted, so the copy constructor is not Called.
4
Let's take a look at the case where a nameless object is Quoted.
#include <iostream>
usingnamespaceStd
classInternet
{
public:
Internet (Char*name,Char*address)
{
cout<< "load constructors" <<endl;
strcpy (internet::name,name);
}
Internet (internet &temp)
{
cout<< "load Copy constructor" <<endl;
strcpy (internet::name,temp.name);
Cin. Get ();
}
~internet ()
{
cout<< "load destructor!";
}
public:
Charname[20];
Charaddress[20];
};
void Main()
{
Internet &a=internet ("china Software development lab", "www.cndev-lab.com");
cout<<a.name;
Cin. Get ();
}
The reference itself is an alias of an object, and it is not related to replication, so the copy constructor is not called, but it is important to note that in C + + it looks like:
Internet &a=internet ("china Software development lab", "www.cndev-lab.com");
is equivalent to:
Internet a ("china software development laboratory", "www.cndev-lab.com");
, observe the location of the call destructor ( this is in the case of main (), and the Nameless object itself is in main ().
Copy-copy constructors for C + + class objects