Constructors, destructor, and assignment functions are the most basic functions of each class. They are so common that they are easy to paralyze. In fact, these seemingly simple functions are as dangerous as the sewers without the top cover.
Each class has only one destructor and one value assignment function, but it can have multiple Constructors (including one copy constructor, and others are called normal constructor ).
If you do not want to write the above functions for any class A, the C ++ compiler will automatically generate four default functions for Class A, for example:
A (void); // default no-parameter Constructor
A (const A & a); // default copy constructor
~ A (void); // default destructor
A & operate = (const A & a); // default value assignment function
This is confusing. Why do programmers need to write functions automatically? The reason is as follows:
<1> if you use the "default no-parameter constructor" and "Default destructor", the chance of "initialization" and "Clearing" is abandoned, the good intentions of C ++ inventor Stroustrup are in vain.
<2> both "Default copy constructor" and "Default Value assignment function" are implemented by "bit copy" instead of "value copy, if the class contains pointer variables, these two functions are doomed to go wrong.
C ++ default constructor:
1. Each class must have a constructor; otherwise, the object cannot be created;
2. If the programmer does not provide any constructor, C ++ provides a default constructor. The default constructor is a non-argument constructor and is only responsible for creating objects, no initialization work;
3. As long as the programer defines a constructor (no matter whether there is no parameter or a constructor), C ++ no longer provides the default constructor. That is, if you define a constructor with parameters for a class and want to create a constructor without parameters, you must define it yourself;
4. Similar to the variable definition, when using the default constructor to create an object, if a global or static object is created, the bitwise mode of the object is 0. Otherwise, the object value is random.
C ++ default copy constructor:
1. The execution sequence of the default copy constructor is the same as that of other user-defined constructor. Execute the construction of the first parent class and the next subclass.
2. The Copy constructor performs the member Copy (memberwise Copy) action on each data member in the class.
3. If the data member is an instance of a class, the copy constructor of this class is called.
4. If the data member is an array, perform bitwise copy on each of the arrays.
5. If a data member is a quantity, such as int or double, assign a value to it by calling the built-in value assignment operator.
See the following code:
// ================================================ ==============================================
// Name: main. cpp
// Author: ShiGuang
// Version:
// Copyright: sg131971@qq.com
// Description: Hello World in C ++, Ansi-style
// ================================================ ==============================================
# Include <iostream>
# Include <string>
Using namespace std;
Class Student
{
Public:
Student ()
{
Cout <"constructor 1" <endl;
}
Student (int k)
{
Cout <"constructor 2" <endl;
I = k;
}
Student (Student const & m)
{
Cout <"copy constructor" <endl;
I = m. I * (-1 );
}
Void p ()
{
Cout <I <endl;
}
~ Student ()
{
Cout <"destructor" <endl;
}
Protected:
Int I;
};
Int main (int argc, char ** argv)
{
Student s (9818 );
// Call constructor 2
S. p ();
Student t (s );
// Call the copy constructor
T. p ();
Student k = s;
// Call the copy constructor
K. p ();
Student * p = new Student (s );
// Call the copy constructor
P-> p ();
Student m;
// Call constructor 1
M = s; // value assignment
M. p ();
Return 0;
}
Running result:
Constructor 2
9818
Copy constructor
-9818
Copy constructor
-9818
Copy constructor
-9818
Constructor 1
9818
Destructor
Destructor
Destructor
Destructor
Next we will discuss the issues of the shortest copy and the deep copy.
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 (the value pointed to by the replication pointer), this process can be called Deep copy, otherwise, if the object has resources but the replication process does not copy the resources (only the address indicated by the pointer is copied), it is considered as a light copy.
Many people will ask, since the system will automatically provide a default copy constructor to process replication, there is no need to customize the copy constructor, in general, this is indeed unnecessary, but in some cases, members in the class body need to open up dynamic heap memory, if we do not customize the copy constructor and let the system process it ourselves, it will lead to confusion about the ownership of heap memory. Imagine that the heap address opened at one end originally belongs to object a. Because of the replication process, object B obtains the heap address opened by object a. Once the program produces a structure, when the heap is released, the computer does not know who the address belongs to. When two consecutive analyses occur, a running error occurs.
For more details, see the following code.
// ================================================ ==============================================
// Name: main. cpp
// Author: ShiGuang
// Version:
// Copyright: sg131971@qq.com
// Description: Hello World in C ++, Ansi-style
// ================================================ ==============================================
# Include <iostream>
# Include <string>
Using namespace std;
Class aa
{
Public:
Aa ()
{
Cout <"Call constructor" <endl;
F = new char [10];
}
~ Aa ()
{
Cout <"Call destructor" <endl;
Delete [] f;
}
Char * f;
};
Int main (int argc, char ** argv)
{
Aa p;
Printf ("p. f = % p \ n", p. f );
Strcpy (p. f, "Computer ");
Cout <p. f <endl;
Aa q (p); // call the default copy constructor
Printf ("q. f = % p \ n", q. f );
Cout <q. f <endl;
Strcpy (p. f, "Software ");
Cout <p. f <endl;
Cout <q. f <endl;
Strcpy (q. f, "Software ");
Cout <p. f <endl;
Cout <q. f <endl;
Return 0;
}
Running result:
Call Constructor
P. f = 003F1048
Computer
Q. f = 003F1048
Computer
Software
Software
Software
Software
Call destructor
Call destructor
Through the above example, we can clearly see that the second object calls the copy constructor, and the address value obtained by q. f is the same as that obtained by p. f, that is, pointing to the same memory area. When the program ends, it will call the Destructor twice, that is, the same pointer executes the delete operation twice. What will happen? This may be a disaster that may damage the heap and the free memory table.
So how can we avoid it? Here we need to use deep copy.
// ================================================ ==============================================
// Name: main. cpp
// Author: ShiGuang
// Version:
// Copyright: sg131971@qq.com
// Description: Hello World in C ++, Ansi-style
// ================================================ ==============================================
# Include <iostream>
# Include <string>
Using namespace std;
Class aa
{
Public:
Aa ()
{
Cout <"Call constructor" <endl;
F = new char [10];
}
Aa (aa const & s)
{
Cout <"Call copy constructor" <endl;
F = new char [10];
Strcpy (f, s. f );
}
~ Aa ()
{
Cout <"Call destructor" <endl;
Delete [] f;
}
Char * f;
};
Int main (int argc, char ** argv)
{
Aa p;
Printf ("p. f = % p \ n", p. f );
Strcpy (p. f, "Computer ");
Cout <p. f <endl;
Aa q (p); // call the copy constructor of the consumer
Printf ("q. f = % p \ n", q. f );
Cout <q. f <endl;
Strcpy (p. f, "Software ");
Cout <p. f <endl;
Cout <q. f <endl;
Strcpy (q. f, "Software ");
Cout <p. f <endl;
Cout <q. f <endl;
Return 0;
}
Running result:
Call Constructor
P. f = 00351048
Computer
Call the copy constructor
Q. f = 00351060
Computer
Software
Computer
Software
Software
Call destructor
Call destructor
Now we can see that p. f and q. f point to different memory areas.
Study Notes from sg131971