In terms of concept, constructor can be considered to be implemented in two phases:
1. Initialization phase;
2. Common computing stage. (The computing stage consists of all the statements in the constructor)
Whether or not the Members display initialization in the constructor initialization list, data members of the class type are always initialized in the initialization phase. Initialization occurs before the start of the computing phase.
Suggestion: Use the constructor to initialize the list.
Note: you must use the initialization method for any const or reference type member and any member of the class type without the default constructor.
You can use constructors to initialize the list to avoid compilation errors.
Explanation: no default constructor class? What does that mean?
In most compilers, a class is declared. If the class has no explicit declaration and constructor definition, the compiler will generate a default constructor in the compilation phase. If you declare a constructor in this class, the compiler will not generate default constructor, but will use your own constructor. To avoid compilation errors, it is best to use the constructor initialization list to initialize objects of this class.
----- Excerpt from C ++ Primer Chinese Version 4th
Class member initialization includes the initialization of Class Object members and class data members. The key to Initialization is the initialization list of the constructor. In the initialization list of the constructor, the order is also required. Only constructors can have the effect of member initialization. Common member functions do not have this function, for example:
[Cpp] void CInit: setXY (int x, int y): mX (x), mY (y)
{
}
Void CInit: setXY (int x, int y): mX (x), mY (y)
{
} This Initialization is incorrect. setXY is not a constructor. Therefore, common member functions can only set the values of variables or objects by assigning values.
[Cpp] void CInit: setXY (int x, int y)
{
MX = x;
MY = y;
}
Void CInit: setXY (int x, int y)
{
MX = x;
MY = y;
} Here, a CInit class is declared as follows:
[Cpp] class CInit
{
Public:
CInit (int x, int y );
Void Show () const;
Private:
Int mX;
Int mY;
};
Void CInit: Show () const
{
Cout <"mX =" <mX <endl
<"MY =" <mY <endl;
}
Class CInit
{
Public:
CInit (int x, int y );
Void Show () const;
Private:
Int mX;
Int mY;
};
Void CInit: Show () const
{
Cout <"mX =" <mX <endl
<"MY =" <mY <endl;
}
I. Basic usage of the constructor initialization list
This is the usage of the normal initialization list
Initialization:
[Cpp] CInit: CInit (int x, int y): mX (x), mY (y)
{
}
CInit: CInit (int x, int y): mX (x), mY (y)
{
} The result is equivalent
Assignment:
[Cpp] CInit: CInit (int x, int y)
{
MX = x;
MY = y;
}
CInit: CInit (int x, int y)
{
MX = x;
MY = y;
}
Ii. Sequence of member Initialization
In the constructor initialization list, the initialization order of members is the order of declared members.
Example 1: James wants to initialize mX with x and then initialize mY
[Cpp] CInit: CInit (int x, int y): mX (x), mY (mX)
{
}
CInit test (2, 3 );
Test. Show ();
CInit: CInit (int x, int y): mX (x), mY (mX)
{
}
CInit test (2, 3 );
Test. Show (); the result is:
[Plain] mX = 2
MY = 2
MX = 2
Both mY = 2mX and mY are successfully initialized.
Example 2: Li Si wants to initialize mY first and then use mY to initialize mX
[Cpp] CInit: CInit (int x, int y): mY (y), mX (mY)
{
}
CInit test (2, 3 );
Test. Show ();
CInit: CInit (int x, int y): mY (y), mX (mY)
{
}
CInit test (2, 3 );
Test. Show (); the result is:
[Plain] mX = 2147344384 (different machines may be inconsistent)
MY = 3
MX = 2147344384 (different machines may be inconsistent)
MY = 3 The result shows that mX is not initialized, and mY is initialized to 3.
It can be seen from this that the constructor executes initialization actions in the declared order of variables. Therefore, in example 2, the constructor first initializes mX, but at this time mY is not initialized, this is the case. In the initialization list of the constructor, it is best to initialize the class according to the declared sequence of the member variables in the class.
Iii. Under what circumstances will the constructor be used to initialize the list?
1. const object
2. Reference Type object
Because the const object and the reference type object can only be initialized and cannot be assigned a value, they must be initialized in the initialization list.
3. Class Object (described below)
4. In constructor, Which of the following is more efficient for value assignment initialization and initialization list initialization? Why?
Let's look at an example and we can see that:
[Cpp] # include <iostream>
Using namespace std;
Class CObj
{
Public:
CObj ()
{
Cout <"Call default constructor" <endl;
}
CObj (const CObj & obj)
{
MX = obj. mX;
Cout <"Call replication constructor" <endl;
}
CObj & operator = (const CObj & obj)
{
If (& obj! = This)
{
MX = obj. mX;
}
Cout <"Data assignment" <endl;
Return * this;
}
Private:
Int mX;
};
Class CInit
{
Public:
CInit (const CObj & obj): mObj (obj)
{
// MObj = obj;
}
Private:
CObj mObj;
};
Int main ()
{
CObj obj;
Cout <endl;
CInit test (obj );
Return 0;
}
# Include <iostream>
Using namespace std;
Class CObj
{
Public:
CObj ()
{
Cout <"Call default constructor" <endl;
}
CObj (const CObj & obj)
{
MX = obj. mX;
Cout <"Call replication constructor" <endl;
}
CObj & operator = (const CObj & obj)
{
If (& obj! = This)
{
MX = obj. mX;
}
Cout <"Data assignment" <endl;
Return * this;
}
Private:
Int mX;
};
Class CInit
{
Public:
CInit (const CObj & obj): mObj (obj)
{
// MObj = obj;
}
Private:
CObj mObj;
};
Int main ()
{
CObj obj;
Cout <endl;
CInit test (obj );
Return 0;
} 1. If the CInit constructor is:
[Cpp] CInit (const CObj & obj): mObj (obj)
{
}
CInit (const CObj & obj): mObj (obj)
{
} Execution result:
[Plain] Call the default constructor
Call the replication Constructor
Call the default constructor
When the replication constructor is called to initialize the mObj object in the initialization list of the constructor CInit, the replication constructor is called once. A total of one behavior is required.
2. If the CInit constructor is:
[Cpp] CInit (const CObj & obj)
{
MObj = obj;
}
CInit (const CObj & obj)
{
MObj = obj;
} Execution result:
[Plain] Call the default constructor
Call the default constructor
Data assignment
Call the default constructor
Call the default constructor
Data assignment
When assigning values to the mObj object in the constructor body, the default constructor is called first, and the operator = value assignment operator is called. A total of two actions are required.
Therefore, we can conclude that the efficiency of using the constructor initialization list for initialization of user-defined class types is higher than that of assigning values to initialization in the constructor body. For built-in types, the efficiency is similar.
5. Example of using the constructor initialization list
[Cpp]/* class member initialization: calculates the rectangle composed of 2 points */
# Include <iostream>
Using namespace std;
Class CCenterPoint
{
Public:
CCenterPoint (int posX, int posY): mPosX (posX), mPosY (posY)
{
}
Void ShowPos () const
{
Cout <"midpoint coordinates between two points: (" <mPosX <"," <mPosY <")" <endl;
}
Private:
Int mPosX;
Int mPosY;
};
Class CArea
{
Public:
CArea (int length, int width): mLength (length), mWidth (width)
{
}
Void ShowArea () const
{
Cout <"rectangular area composed of 2 points:" <mLength * mWidth <endl;
}
Private:
Int mLength;
Int mWidth;
};
Class CRect
{
Public:
CRect (int posX1, int posY1, int posX2, int posY2)
: MPoint (posX1 + posY1)/2, (posX2 + posY2)/2 ),
MArea (posX2-posX1, posY2-posY1)
{
}
Void Show () const
{
MPoint. ShowPos ();
MArea. ShowArea ();
}
Private:
CCenterPoint mPoint;
CArea mArea;
};
Int main ()
{
CRect rect (10,100, 20,200 );
Rect. Show ();
Return 0;
}
/* Class member initialization: Find a rectangle composed of two points */
# Include <iostream>
Using namespace std;
Class CCenterPoint
{
Public:
CCenterPoint (int posX, int posY): mPosX (posX), mPosY (posY)
{
}
Void ShowPos () const
{
Cout <"midpoint coordinates between two points: (" <mPosX <"," <mPosY <")" <endl;
}
Private:
Int mPosX;
Int mPosY;
};
Class CArea
{
Public:
CArea (int length, int width): mLength (length), mWidth (width)
{
}
Void ShowArea () const
{
Cout <"rectangular area composed of 2 points:" <mLength * mWidth <endl;
}
Private:
Int mLength;
Int mWidth;
};
Class CRect
{
Public:
CRect (int posX1, int posY1, int posX2, int posY2)
: MPoint (posX1 + posY1)/2, (posX2 + posY2)/2 ),
MArea (posX2-posX1, posY2-posY1)
{
}
Void Show () const
{
MPoint. ShowPos ();
MArea. ShowArea ();
}
Private:
CCenterPoint mPoint;
CArea mArea;
};
Int main ()
{
CRect rect (10,100, 20,200 );
Rect. Show ();
Return 0;
} Execution result:
[Plain] midpoint coordinates between two points: (55,110)
Rectangular area composed of 2 points: 1000
Midpoint coordinates between two points: (55,110)
Rectangular area composed of 2 points: 1000
Happy Learning!
From the gzshun Column