Introduction: This is a detailed page of C ++ copy constructor and value assignment constructor. It introduces the knowledge, skills, and experience related to C/C ++, and some C/C ++ source code.
Note: classes that contain dynamically assigned members should provide copy constructors and overload the "=" value assignment operator.
The following examples will be used:
Class cexample
{
Public:
Cexample () {pbuffer = NULL; nsize = 0 ;}
~ Cexample () {Delete pbuffer ;}
Void Init (int n) {pbuffer = new char [N]; nsize = N ;}
PRIVATE:
Char * pbuffer; // class object contains pointer, pointing to dynamically allocated memory resources
Int nsize;
};
The main feature of this class is to include pointers to other resources.
Pbuffer points to a memory space allocated in the heap.
I. copy constructors
Int main (INT argc, char * argv [])
{
Cexample theobjone;
Theobjone. init40 );
// Another object needs to be initialized and called object 1.
Cexample theobjtwo = theobjone;
...
}
Statement "cexample theobjtwo = theobjone;" use theobjone to initialize theobjtwo.
The complete method is to copy the values of all members in the memory.
After completion, theobjtwo. pbuffer = theobjone. pbuffer.
That is, they will point to the same place. Although the pointer is copied, the space to which it points is not copied, but shared by two objects. In this way, the objects are not independent, and the deletion of spaces poses a risk.
Therefore, necessary measures are required to avoid such situations.
Review the specific process of the following statement: first, create the object theobjtwo, call its constructor, and then the Member is copied.
You can add operations in the constructor to solve the problem of pointer members.
Therefore, in addition to providing default constructor, C ++ also standardizes another special constructor: copy constructor. In the preceding statement, if a copy constructor is defined in the class, when the object is created, the copy constructor is called. In the copy constructor, you can refer to the input variables, copy the resource pointed to by the pointer.
The format of the copy constructor is: constructor name (Object reference)
The cexample class provided after the copy constructor is defined:
Class cexample
{
Public:
Cexample () {pbuffer = NULL; nsize = 0 ;}
~ Cexample () {Delete pbuffer ;}
Cexample (const cexample &); // copy the constructor
Void Init (int n) {pbuffer = new char [N]; nsize = N ;}
PRIVATE:
Char * pbuffer; // class object contains pointer, pointing to dynamically allocated memory resources
Int nsize;
};
Cexample: cexample (const cexample & rightsides) // definition of copy constructor
{
Nsize = rightsides. nsize; // copy a regular member
Pbuffer = new char [nsize]; // copy the content pointed to by the pointer
Memcpy (pbuffer, rightsides. pbuffer, nsize * sizeof (char ));
}
In this way, when a new object is defined and initialized with an existing object, cexample (const cexample & rightsides) will be called, and the existing object will be passed to the constructor using the alias rightsides for copying.
In principle, a copy constructor should be provided for all classes that contain dynamically assigned members.
Another method of calling the copy constructor.
When an object is directly transmitted as a parameter to the function, the function will create a temporary copy of the object. This copy process will also be called the same copy constructor.
For example:
Bool testfunc (cexample OBJ );
Testfunc (theobjone); // The object is directly used as a parameter.
Bool testfunc (cexample OBJ)
{
// Obj-specific operations are actually performed on temporary copies after replication.
}
Another case is also related to temporary objects.
When a local object in the function is returned to the function caller, a temporary copy of the local object will also be created, and the copy constructor will also be called.
Ctest func ()
{
Ctest thetest;
Return thetest
}
Ii. overload of value assignment
The following code is similar to the previous example.
Int main (INT argc, char * argv [])
{
Cexample theobjone;
Theobjone. INIT (40 );
Cexample theobjthree;
Theobjthree. INIT (60 );
// Now an object Value assignment operation is required. The original content of the assigned object is cleared and filled with the content of the right object.
Theobjthree = theobjone;
Return 0;
}
"=" Is also used, but it is different from the example in "1.". In the example of "1.", "=" indicates initialization in the object declaration statement. More often, such initialization can also be represented by parentheses.
For example, cexample theobjone (theobjtwo );
In this example, "=" indicates the value assignment operation. Copy the content of theobjone to theobjthree, which involves discarding the original content of theobjthree and copying new content.
However, the default operation of "=" only copies the value of the member variable. Old values are naturally discarded.
Because the object contains pointers, it will cause adverse consequences: the pointer value is discarded, but the content pointed to by the pointer is not released. The pointer value is copied, but the content indicated by the pointer is not copied.
Therefore, in addition to providing a copy constructor, classes that contain dynamically assigned members should also consider overloading the "=" value assignment operator symbol.
Class Definition changed:
Class cexample
{
...
Cexample (const cexample &); // copy the constructor
Cexample & operator = (const cexample &); // The Value assignment operator is overloaded.
...
};
// Overload the value assignment operator
Cexample & cexample: Operator = (const cexample & rightsides)
{
Nsize = rightsides. nsize; // copy a regular member
Char * temp = new char [nsize]; // copy the content pointed to by the pointer
Memcpy (temp, rightsides. pbuffer, nsize * sizeof (char ));
Delete [] pbuffer; // Delete the content pointed by the original pointer (put the delete operation behind it to avoid content loss in special cases of X = x)
Pbuffer = temp; // create a new point
Return * This
}
3. Copy the code that uses the value assignment operator to overload the constructor.
Cexample: cexample (const cexample & rightsides)
{
Pbuffer = NULL;
* This = rightsides // "=" after the overload is called"
}
In order to better understand the copy constructor, I also have two sentences:
1. Why is a copy constructor different from a constructor?
A: The copy constructor is actually a constructor, but its parameter is a reference of the const class's own object. If there is no pointer member in the class (the pointer member points to the dynamically applied space), there is no need to write a copy constructor. We know that if there is a class cobj, it has produced an object obja, And now it uses cobj to create objb, if the program uses the statement objb = obja; that is to say, assign values to objb directly using the obja data. This is no problem for general classes, but if a member of char * pstr in cobj is used to store the address of the dynamically applied string, in obja, the new method is used to dynamically apply for the memory and make the obja. pstr points to the requested space, after ojbb = ojba, obja. pstr and objb. pstr points to the space at the same time, so that no one knows who is responsible for releasing the space, it is likely that the same memory is released twice. Apply for obja first by using the copy constructor. pstr points to the space of the space size, and then copies the space content, so that it does not point to the same memory. Each has its own applied memory, and is responsible for releasing its own applied memory, this solved the problem just now. Therefore, the "copy" here copies the content of the dynamically applied space, rather than the data of the class itself. Note that the parameters of the copy constructor are object references rather than object pointers. As for why the reference should be used, it cannot be understood by the pointer for the moment. 2. Why do I need to overload the = value assignment operator?
A: In the following example, when you use the statement objb = obja, The pstr of objb may already point to the dynamically applied space. If you simply overwrite the address that it points, this will cause memory leakage. Therefore, you need to reload the = value assignment operator. In the overload function, determine that if pstr has pointed to the dynamically applied space, release it first. 3. Copy the constructor and the = value assignment operator overload relationship.
A: From the original example, we can see that the = assignment operator overload is much more than the copy constructor, except for copying the memory data dynamically applied by the constructor, the memory space originally applied for is also released. Therefore, the implementation of the copy constructor provided at the end of the original text can be completed using the overload of the = value assignment operator. 4. When will the copy constructor be called?
A. the object's direct value assignment will also call the copy constructor (since the = value assignment operator is overloaded, why do I need to call the copy constructor ?);
B. If the function parameter is passed by value, the copy constructor is also called;
C. If the function returns a value, the copy constructor is also called. 5. As in question 4, since the = value assignment operator is overloaded, why do I need to call the copy constructor?
A: Write a small program to test it. /Compare the differences between an operator overload function and a copy constructor
# Include <iostream>
Using namespace STD;
# Include <cstring>
Class namelist
{
Char * Name;
Public:
Namelist (char * P) // constructor with Parameters
{
Name = new char [strlen (p) + 1];
If (name! = 0) strcpy (name, P );
}
Namelist () {}; // default constructor
Namelist (namelist &); // copy the constructor
Namelist & operator = (char * P );
Namelist & operator = (namelist &);
Void display () {cout <name <Endl ;}
~ Namelist ()
{
Delete [] Name;
}
};
Namelist: namelist (namelist & A) // defines the copy constructor.
{
Name = new char [strlen (A. Name) + 1];
If (name! = 0) strcpy (name, A. Name );
}
Namelist & namelist: Operator = (char * P )//
// The first overload assignment operator to assign values to objects using Constants
{
Name = new char [strlen (p) + 1];
If (name! = 0) strcpy (name, P );
Return * this;
}
Namelist & namelist: Operator = (namelist &)
// The second overload assignment operator completes the assignment between class objects
{
If (this! = & A) // first check whether the value is assigned to itself. If not
{
Delete [] Name; // re-allocate the required space to the object and copy the string to ensure that the target object and the original object have their own copy strings, thus completing the deep copy.
Name = new char [strlen (A. Name) + 1];
If (name! = 0) strcpy (name, A. Name );
}
Return * this;
}
Int main ()
{
Namelist N1 ("first object"), N2 ("second object"); // call a constructor with Parameters
Namelist N3; // default constructor
Cout <"data before Value assignment:" <Endl;
N1.display ();
N2.display ();
N3 = "third object"; // call the first overload assignment operator Function
N2 = N1; // call the second overload assignment operator Function
Namelist N4 (N2); // call the copy constructor.
Namelist N5 = N3; // call the copy constructor Function
Namelist N6 = "Sixth object"; // call a constructor with parameters equivalent ().
Cout <"value-assigned Data:" <Endl;
N1.display ();
N2.display ();
N3.display ();
N4.display ();
N5.display ();
Return 0;
}
Summary: The copy constructor occurs in the following three situations:
In C ++, the following three objects need to call the copy constructor:
1) An object passes in the function body as a value;
2) an object is returned from the function by passing values;
3) one object needs to be initialized through another object;
The definition of deep copy and shallow copy can be simply understood as: If a class has resources (heap, or other system resources), when the object of this class is copied, this process can be called Deep copy. If the object has resources but the copying process does not copy resources, it is considered as a light copy. From: http://blog.csdn.net/qiufei230/article/details/6196570