I'm trying to understand the real difference between the following Classes.
class A
{
public:
A()
:width(500)
,height(300){};
int width;
int height;
};
class B
{
public:
B()
{
width = 500;
height = 300;
};
int width;
int height;
};
class C
{
public:
int width = 500;
int height = 300;
};
Which one do you think is the best way to initialize width
and height
variables in a class?
Should I stick to one way over the others?
This excerpt has been taken from "Inside the C++ Object Model" by Stanley B. Lippman.
You must use the member initialization list in the following cases in order for your program to compile:
1. When initializing a reference member
2. When initializing a const member
3. When invoking a base or member class constructor with a set of arguments
4. A few efficiency cases. (Here the program is correct w/o member initialization list)
For points 1-3, member initialization list is a must.
For point 4, it is not compulsory.
For example(point 4), given :
class Word {
String _name;
int _cnt;
public:
// not wrong, just naive ...
Word() {
_name = 0;
_cnt = 0;
}
};
This implementation of the Word
constructor initializes _name
once, then overrides the initialization with an assignment, resulting in the creation and the destruction of a temporary String
object.
A significantly more efficient implementation would have been coded:
// preferred implementation
Word::Word : _name( 0 )
{
_cnt = 0;
}
Due to this optimisation, a lot of people prefer member initialization list, as a default approach to write constructors.
// some insist on this coding style
Word::Word()
: _cnt( 0 ), _name( 0 )
{}
A reasonable question to ask at this point is, what actually happens to the member initialization list?
The compiler iterates over the initialization list, inserting the initializations in the proper order within the constructor prior to any explicit user code.
For example, the previous Word
constructor is expanded as follows:
// Pseudo C++ Code
Word::Word( /* this pointer goes here */ )
{
_name.String::String( 0 );
_cnt = 0;
}
Note : The order in which the list entries are set down is determined by the declaration order of the members within the class declaration, not the order within the initialization list. In this case,
_name
is declared before_cnt
inWord
and so is placed first.
So coming back to your question :
class B
is fine(since you are using primitive datatypes).
class A
will generate the same code as class B
As for class C
, the default constructor is first called, and then initialization of width
and height
would happen. This method should be preferred when there are going to be more than 1 constructor, and for each constructor width
and height
need to be defaulted to your desired values.
However, since the advent of C++11, and use of {}
as uniform initialization, a more recommended approach for writing class C
would be :
class C
{
public:
int width {500};
int height {300};
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With