The default constructor in C + + is a constructor with no formal parameters . Exactly, as defined in the C + + Primer: The default constructor is used whenever an object is defined without an initialization. The constructor that provides the default arguments for all the parameters also defines the default constructor.
The default constructor for the composition, which is the default constructor that the compiler automatically generates . Description in C + + Primer: A class that even defines only one constructor, the compiler will no longer generate a default constructor. This rule is based on the possibility that if a class needs to control object initialization in some cases, it is likely that the class will need to be controlled in all cases. The compiler automatically generates a default constructor only if a class does not have a constructor defined.
It is important to note that custom constructors include copy constructors . This means that the compiler does not automatically generate a default constructor in the following scenario, and the code will fail. After removing the copy constructor, there is no problem.
The functions that the compiler automatically generates for a class include default constructors, copy constructors, destructors, and assignment functions. However, if you define a copy constructor, the default constructor compiler is not automatically generated. However, other functions are automatically generated when you define a default constructor.
#include <iostream>using namespace Std;class base{public://constructor//base () {//cout<< "default constructor invoke! " <<endl;//}//base (int D) {//this->data=d;//cout<< "constructor invoke!" <<endl;//}//copy constructor Base (const base &B) {cout<< "copy constructor invoke!" <<endl;this->data=b.data;} Assignment operator Base & operator= (const Base &b) {cout<< "operator Constructor invoke!" <<endl;this->data=b.data;} 7 constructor ~base () {cout<< "Deconstructor invoke!" <<endl;} Private:int data;}; int main () {Base B;return 0;}
First use the following code to test the invocation of the default constructor, constructor, copy constructor, assignment operator:
#include <iostream>using namespace Std;class base{public://constructor Base () {cout<< "default constructor invoke!" <<endl;} Base (int D) {this->data=d;cout<< "constructor invoke!" <<endl;} Copy constructor Base (const base &B) {cout<< "copy constructor invoke!" <<endl;this->data=b.data;} Assignment operator void operator= (const Base &b) {cout<< "operator Constructor invoke!" <<endl;this->data=b.data;} destructor ~base () {cout<< "Deconstructor invoke!" <<endl;} Private:int data;}; int main () {base B (1);//constructor call base b2=b;//copy constructor call base b3;//default constructor call b3=b;//assignment operator call return 0;}
The results of the implementation are as follows:
The results are the same in both g++ and vs.
Then add a function to test:
#include <iostream>using namespace Std;class base{public://constructor Base () {cout<< "default constructor invoke!" <<endl;} Base (int D) {this->data=d;cout<< "constructor invoke!" <<endl;} Copy constructor Base (const base &B) {cout<< "copy constructor invoke!" <<endl;this->data=b.data;} Assignment operator void operator= (const Base &b) {cout<< "operator Constructor invoke!" <<endl;this->data=b.data;} 7 constructor ~base () {cout<< "Deconstructor invoke!" <<endl;} Base Play (base b) {return B;} Private:int data;}; int main () {base B (1);//constructor call base b2=b;//copy constructor call base b3;//default constructor call b3=b;//assignment operator call B.play (2);//Constructor call, Copy constructor call (caused by function return) return 0;}
The result is as follows: When the function B.play (2) executes, the constructor is first used (that is, the constructor that accepts an int variable) for implicit type conversion, that is, the constructor is called once. Note that it is not possible to do this if the play parameter is of type b&. Otherwise, there will be an error.
Then use the direct call when:
#include <iostream>using namespace Std;class base{public://constructor Base () {cout<< "default constructor invoke!" <<endl;} Base (int D) {this->data=d;cout<< "constructor invoke!" <<endl;} Copy constructor Base (const base &B) {cout<< "copy constructor invoke!" <<endl;this->data=b.data;} Assignment operator void operator= (const Base &b) {cout<< "operator Constructor invoke!" <<endl;this->data=b.data;} 7 constructor ~base () {cout<< "Deconstructor invoke!" <<endl;} Base Play (base b) {return B;} Private:int data;}; int main () {base B (1);//constructor call base b2=b;//copy constructor call base b3;//default constructor call b3=b;//assignment operator call B.play (2);//Constructor call, Copy constructor call (caused by function return) B.play (b);//<span style= "font-size:11.8181819915771px; Font-family:arial, Helvetica, Sans-serif; > First copy constructor call is a constructor parameter, second copy constructor call is function return value </span>return 0;}
The output structure is as follows:
At first it was not clear why it was two copies of the constructor call. Then print out the address of each object.
VS Results:
As a result of g++, we can find that the order of the result parameters in the g++ is still regular, but the VS seems to have no regularity.
This is still not understood, but compared with the following code is easier to understand the situation:
#include <iostream>using namespace Std;class base{public://constructor Base () {cout<< "default constructor invoke!" << (int *) This<<endl;} Base (int D) {this->data=d;cout<< "constructor invoke!" << (int *) This<<endl;} Copy constructor Base (const base &B) {cout<< "copy constructor invoke!" << (int *) This<<endl;this->data=b.data;} Assignment operator void operator= (const Base &b) {cout<< "operator Constructor invoke!" << (int *) This<<endl;this->data=b.data;} 7 constructor ~base () {cout<< "Deconstructor invoke!" << (int *) This<<endl;} Base Play (base b) {return B;} Private:int data;}; int main () {base B (1);//constructor call base b2=b;//copy constructor call base b3;//default constructor call b3=b;//assignment operator call B.play (2);//Constructor call, Copy constructor call (caused by function return) B.play (b);//First copy constructor call is a constructor parameter, second copy constructor call is function return value cout<< "---------------" <<endl; Base B4=b.play (2);cout<< "---------------" <<endl; Base B5=b.play (b);cout<< "---------------" <<endl;return 0;}
The results in g++ are:
You can find Base b4=b.play (2), and B.play (2); This line of code compared to the location of the destructor has changed, before the two consecutive destructors, now replaced by the first one, and then after the end of the function and then the destruction. And the second copy of the constructor creates an object that is refactored after the function ends (according to the object's address). The case may be that the second copy constructor is caused by the function returning the object. Because the parameter B is destroyed after the function play call ends, B is copied to a new memory area. the memory layout when calling B.play (2) might be like this (drawn according to the above address):
In order to verify this test, you can let the play function not return the object B, the code is as follows:
#include <iostream>using namespace Std;class base{public://constructor Base () {cout<< "default constructor invoke!" << (int *) This<<endl;} Base (int D) {this->data=d;cout<< "constructor invoke!" << (int *) This<<endl;} Copy constructor Base (const base &B) {cout<< "copy constructor invoke!" << (int *) This<<endl;this->data=b.data;} Assignment operator void operator= (const Base &b) {cout<< "operator Constructor invoke!" << (int *) This<<endl;this->data=b.data;} 7 constructor ~base () {cout<< "Deconstructor invoke!" << (int *) This<<endl;} void Play (Base b) {}private:int data;}; int main () {base B (1);//constructor call base b2=b;//copy constructor call base b3;//default constructor call b3=b;//assignment operator call B.play (2);//Constructor call B.play (b);// Call a copy constructor return 0;}
You can find the call to copy the constructor less once:
There should be a clear understanding of when the constructor, copy constructors, and assignment operators should be called.
C + + constructor, copy constructor, destructor