Using the c++11 standard, I can initialize class members in two ways:
class MyClass
{
private:
int a = 5;
};
or
class MyClass
{
private:
int a;
public:
MyClass()
{
a = 5;
}
};
Is either method superior to the other for any reason, or is it more an individual style choice?
The second example is not initialisation.
So, of the two examples, the first is the best way to initialise class members.
The traditional way to initialise looks like this:
class MyClass
{
private:
int a;
public:
MyClass()
: a(5)
{}
};
Though we now have inline initialisers as in your first example, since C++11.
This page from the Standard C++ Foundation suggests that, all else being equal, you should prefer to use an initializer list. That is:
Prefer
class Foo {
public:
Foo(int bar) : m_bar(bar) { }
private:
int m_bar;
};
over
class Foo {
public:
Foo(int bar) {
m_bar = bar;
}
private:
int m_bar;
};
Their rationale:
Consider the following constructor that initializes member object x_
using an initialization list: Fred::Fred() : x_(whatever) { }. The
most common benefit of doing this is improved performance. For
example, if the expression whatever is the same type as member
variable x_, the result of the whatever expression is constructed
directly inside x_ — the compiler does not make a separate copy of the
object. Even if the types are not the same, the compiler is usually
able to do a better job with initialization lists than with
assignments.
The other (inefficient) way to build constructors is via assignment,
such as: Fred::Fred() { x_ = whatever; }. In this case the expression
whatever causes a separate, temporary object to be created, and this
temporary object is passed into the x_ object’s assignment operator.
Then that temporary object is destructed at the ;. That’s inefficient.
As if that wasn’t bad enough, there’s another source of inefficiency
when using assignment in a constructor: the member object will get
fully constructed by its default constructor, and this might, for
example, allocate some default amount of memory or open some default
file. All this work could be for naught if the whatever expression
and/or assignment operator causes the object to close that file and/or
release that memory (e.g., if the default constructor didn’t allocate
a large enough pool of memory or if it opened the wrong file).
Conclusion: All other things being equal, your code will run faster if
you use initialization lists rather than assignment.
Regarding default initialization (such as Foo(): m_bar(5) { }) I would also go with the initializer list approach (or the C++11 member initialization approach) just for consistency with the above guideline.
Related
Why did the creator of C++ decide to use constructor initializer list to initialize base classes? Why didn't he instead choose to use syntax like the second comment line in the following code?
class A{
public:
A() { }
};
class B : A{
public:
B() : A() { } // Why decide to use this one, using constructor initializer, to initialize base class?
B() { A(); } // Why not choose this one? It's easy for me to understand if it was possible.
};
int main(int argc, char *argv[]){
/* do nothing */
}
The advantage of using an initializer list is, that you have a completely initialized object in the body of the constructor.
class A {
public:
A(const int val) : val(val) { }
private:
const int val;
};
class B : A{
public:
B() : A(123) {
// here A and B are already initialized
}
};
So you have a guarantee that all members, even those of the parent, are not in an undefined state.
Edit
In the example of the question it is not necessary to call the base class in the initializer list, this is done automatically. So I slightly modified the example.
I can see a few possible alternatives to the current C++ rule that base classes and data members of a class type are initialised in the mem-initialiser list of the class type's constructor(s). They all come with their set of issues, which I will discuss below.
But first, note that you cannot simply write a derived constructor like this:
struct Derived : Base
{
Derived()
{
Base(42);
}
};
and expect the line Base(42); to call the base class constructor. Everywhere else in C++, such a statement creates a temporary object of type Base initialised with 42. Changing its meaning inside a constructor (or just inside its first line?) would be a syntax nightmare.
Which means that new syntax would need to be introduced for this. In the rest of this answer, I will use a hypothetical construct __super<Base> for this.
Now on to discuss possible approaches which would be closer to your desired syntax, and present their problems.
Variant A
Base classes are initialised in the constructor body, while data members are still initialised in the mem-initialiser list. (This follows the letter of your question the closest).
The would have the immediate problem of stuff executing in different order than it's written. For very good reasons, the rule in C++ is that base class subobjects are initialised before any data members of the derived class. Imagine this use case:
struct Base
{
int m;
Base(int a) : m(a) {}
};
struct Derived
{
int x;
Derived() :
x(42)
{
__super<Base>(x);
}
};
Written like this, you could easily assume x would be initialised first and then Base would be initialised with 42. However, that would not be the case and instead reading x would be undefined.
Variant B
Mem-initialiser lists are removed altogether, base classes are initialised using __super, and data members are simply assigned in the constructor body (pretty much the way Java does it).
This cannot work in C++ because initialisation and assignment are fundamentally different concepts. There are types where the two operations do vastly different things (e.g. references), and types which are not assignable at all (e.g. std::mutex).
How would this approach deal with a situtation like this?
struct Base
{
int m;
Base(int a) : { m = a; }
};
struct Derived : Base
{
double &r;
Derived(int x, double *pd)
{
__super<Base>(x); // This one's OK
r = *pd; // PROBLEM
}
};
Consider the line marked // PROBLEM. Either it means what it normally does in C++ (in which case it assigns a double into a "random place" which the uninitialised reference r references), or we change its semantics in constructors (or just in initial parts of a constructor?) to do initialisation instead of assignment. The former gives us a buggy program while the latter introduces totally chaotic syntax and unreadable code.
Variant C
Like B above, but introduce special syntax for initialising a data member in the constructor body (like we did with __super). Something like __init_mem:
struct Base
{
int m;
Base(int a) : { __init_mem(m, a); }
};
struct Derived : Base
{
double &r;
Derived(int x, double *pd)
{
__super<Base>(x);
__init_mem(r, *pd);
}
};
Now, the question is, what have we achieved? Previously, we had the mem-initialiser list, a special syntax to initialise bases and members. It had the advantage that it made clear these things happen first, before the constructor body starts. Now, we have a special syntax to initialise bases and members, and we need to force the programmer to put it at the start of the constructor.
Note that Java can get away with not having a mem-initialiser list for several reasons which don't apply to C++:
The syntax for creating an object is always new Type(args) in Java, whereas Type(args) can be used in C++ to construct objects by value.
Java only uses pointers, where initialisation and assignment are equivalent. For many C++ types, there operations are distinct.
Java classes can only have one base class, so using just super is enough. C++ would need to differentiate which base class you're referring to.
B() : A() { }
This will initialize the base class in user defined way.
B() { A(); }
This will NOT initialize the base class in user defined way.
This will create an object inside of constructor i.e B(){}
I think first initialization has better readability compared to the second and you can also deduce class hierarchy.
Here is an example of my question:
class MyBaseClass
{
public:
MyBaseClass(): my_bool(false), my_value(0)
{}
MyBaseClass(bool b, int i): my_bool(b), my_value(i)
{}
private:
bool my_bool;
int my_value;
}
class MyDerivedClass1 : public ::MyBaseClass
{
public:
MyDerivedClass1(double d): my_double(d)
{}
private:
double my_double;
}
class MyDerivedClass2 : public ::MyBaseClass
{
public:
MyDerivedClass2(double d): MyBaseClass(), my_double(d)
{}
private:
double my_double;
}
Why isn't the MyDerivedClass1 an ok way to initialize my derived class versus having to explicitly initialize the base class like in MyDerivedClass2?
I guess I don't understand why I can't just rely on C++ calling my base constructor? I know if I wanted them initialized to something different I'd have to call the other constructor in my initialization list, but all I want is the base constructor to be called anyway.
There is no difference between providing a default-constructed base class in the initializer list or not providing it. What you use if entirely your style. (or the company)
In general, I would say you have 2 options (let's keep constructors out of scope), assuming you always initialize your members.
Option 1: Initialize all members in the init-list.
This option should be used if you are C++98-compatible. It has as advantage that you are defining all construction parameters in a single list, making it easy to search through. (Unless you have 50+ members)
The disadvantage of this option is a lot of duplication when you have multiple constructors.
With this, you can have 3 variants for them:
Skip the default-initialized classes, this makes the list shorter though it's hard to check if you have intended to 'forget' it. (Think replacing a class by a ptr to it)
Default initialize all members, this makes the list longer, though indicates clearly the intent
Explicitly provide the class you are initializing, by copy contructing with a tempuary
Option 2: Initialize all members on declaration, except for constructor parameters
This option assumes you initialize everything in the class declaration. Yet again you can explicitly call the default constructor or not, preferably with braced init, as round braces are interpreted as a function declaration.
In the initializer list you only have to put the members which are linked to the construction parameters.
The advantage of this option is readability (especially for large classes). The disadvantage is that this limits your compiler options to 'modern' compilers.
Base classes
If we again consider base classes and look at them as if they were members, the consistent way would be to declare them explicitely for option 1 and don't write them for option 2.
Personnally I like option 2, as I too often encounter classes with too many members and checking if all members are initialized is easier by hand with this one.
Option 1 however is often used because of legacy in order to keep the code consistent.
POD
Important to mention are the PODs (Plain old datatype), like int, double ...
If you don't initialize them you get some random data. This makes it important to explicitly intialize them, regardless of the method you use to do so.
Conclusion
So in the end, it's all a matter of style with no functional difference.
Although in most cases there isn't a semantic difference and the issue is mostly one of style, there is one case where it is a difference: when the default constructor of the base class is not user-provided.
The difference comes from the fact that a base that is not in the member initializer list is default-initialized, while explicitly writing Base() value-initializes it, which performs zero-initialization if the default constructor isn't user-provided.
Thus:
struct A { int i; };
struct B : A {
B() : j(i) {} // may be undefined behavior
int j;
};
struct C : A {
C() : A(), j(i) {} // OK; both i and j are zero
int j;
};
I am just beginning to learn C++, and am a little confused by the interplay of instantiation, constructor declaration, and inheritance... I think I'm beginning to wrap my head around everything, but I'd like to make sure I've conceptualized things correctly. I've provided a a class and a list of what I think is going on:
class Classy{
private:
int foo1;
int foo2;
public:
//constructor 1
Classy() { foo1 = 0; foo2 = 0; }
//constructor 2
Classy(int bar1) : foo1(bar1), foo2(0) {}
//constructor 3
Classy(int bar1, int bar2) : foo1(bar1) { foo2 = bar2; }
};
Constructor 1 does things the way I'm used to; a call to the constructor sets the foo properties via assignment.
Constructor 2 uses inherited constructors from the int class.
Constructor 3 is a combination of the above.
Inherited constructors can also be from a class' parent - for example:
Child(args) : Parent(args) { ...extras }
which more or less acts like Child(args) { super(args); ...extras } in the languages I'm more familiar with. If we additionally have complex properties (say prop1 is a complex classes - a string or something), then we can instantiate them with their constructors through something like this:
Child(args) : Parent(args), prop1(args) { ...extras }
Does that sum everything up properly? Are there any aspects that I'm missing, or useful elaborations on what I've stated?
You're abusing the term inherited.
Those are subobject constructors, and subobjects include both member variables and base class subobjects. The word inheritance only goes with base class subobjects. The corresponding word for member subobjects is composition.
Using the ctor-initializer list is better than assignment inside the constructor body for a couple reasons:
It can be used for types that have no default constructor.
It can be used for types that can't be assigned, such as references and const member variables.
It is more efficient, because it doesn't require first creating state with the default constructor that simply gets replaced.
You can also use functions and arbitrary expressions when building the parameter lists for the subobject constructors -- they don't have to simply be the arguments passed to your constructor.
If you use an empty pair of parentheses, you'll get value-initialization of a sub-object, instead of default initialization. If there's a default constructor, these are the same. Otherwise, value initialization will get your subobject zeroed, while default initialization will leave an indeterminate, possibly illegal state.
In C++11, you often want to use the universal initializer syntax with {} instead of () when invoking subobject constructors.
Here's an example where these syntaxes are useful:
class Classy
{
// private is the default access specifier for classes
int bar[100];
const std::array<int, 100> baz;
static std::array<int, 100> make_array(int x)
{
std::array<int, 100> retval;
for( int i = 0; i < 100; ++i )
retval[i] = i * x;
return retval;
}
public:
//constructor 1
Classy() : bar{}, baz{} {}
//constructor 2
Classy(int bar1) : bar{}, baz{make_array(bar1)} {}
};
This question already has answers here:
What is this weird colon-member (" : ") syntax in the constructor?
(14 answers)
Closed 8 years ago.
I have been working in C++ for some time now, but I am unsure about the difference between the two options:
public : Thing(int _foo, int _bar): member1(_foo), member2(_bar){}
and
public : Thing(int _foo, int _bar){
member1 = _foo;
member2 = _bar;
}
I have a feeling that they do the same thing, but is there a practical difference between these 2 syntaxes. Is one of these safer then the other, and do they handle default parameters differently.
Not totally accustomed to the first example so if I made a mistake on it I apologize.
They are not the same if member1 and member2 are non-POD (i.e. non-Plain Old Data) types:
public : Thing(int _foo, int _bar){
member1 = _foo;
member2 = _bar;
}
is equivalent to
public : Thing(int _foo, int _bar) : member1(), member2(){
member1 = _foo;
member2 = _bar;
}
because they will be initialized before the constructor body starts executing, so basically twice the work is done. That also means, if the type of these members don't have default constructor, then your code will not compile.
The first one is the recommended best practice, as it is more idiomatic and avoids re-initializing fields for types which do have a default constructor (i.e. non-primitive types).
When you only initialize a member inside the constructor body, the compiler generates a default member initialization statement for you if it can, so you end up doubly initializing it. This may not be a big deal in some cases, but may be serious performance overhead if constructing the object is expensive.
Update
However, user defined types without a(n explicitly defined or generated) default constructor can't be initialized this way, so a compiler error is produced. The same is true for const and reference fields - these can only be initialized explicitly in the member initializer list.
The only thing to add to Péter Török answer is that the Initializer List is the only way to initialize const members of objects, i.e.:
class foo
{
public:
foo(int value)
: myConstValue(value)
{};
foo()
{
myConstValue = 0; // <=== Error! myConstValue is const (RValue), you can't assign!
};
private:
const int myConstValue;
}
In your example code, the first one in constructor initialization and second one is assignment inside constructor body.
Constructor initialization list is the best way to do all member initialization because it improves performance.
class A
{
string name;
public:
A(string myname):name(myname) {}
}
In above case compiler will not create a temporary object to do the initialization. However in the following case:
A::A()
{
name = myname;
}
A separate temporary object is created, and this temporary object is passed to string's assignment operator to assign to name. Then the temporary object is destroyed, which is not quite efficient.
Note: It is mandatory that a reference or a const member must be intialized in a constructor initialization list. They cannot be 'assigned' in the body of the constructor.
Apart from other answers, I would like mention that constructor initialization only for initialize
member variables.
class Demo
{
int a;
int b;
public:
Demo(int a,int b):a(a),b(b)
{
}
};
if we initialize a and b inside constructor it would be self assignment.
First is initialization, using an initializer list and the second is default construction and then assignment. The first one is at least as fast as the second one and is preferable to the second one.
I'm new to C++, and the whole idea of classes - I'm still reading a book to try and learn. The book I'm reading says that when I construct a class, I can assign default values by doing this:
class foo {
public:
foo(char c, int i);
private:
char exampleChar;
int exampleInt;
};
foo::foo(char c, int i):
exampleChar(c),
exampleInt(i)
{}
This code (to me) looks very messy, and doesn't follow rules that I'm used to in other languages. My question is, what's the difference between doing the above, and this (below, which I personally think looks a lot cleaner)?
foo::foo(char c, int i) {
exampleChar = c;
exampleInt = i;
}
Sort of things I'm thinking about are: are there performance/efficiency issues if done on a large scale - or is it exactly the same?
The first way, by doing : exampleChar(c), exampleInt(i) is called an initializer list.
If you do it the second way, the two variables are default constructed first1, then you assign them a value. (When the actual body of the constructor is entered, anything that hasn't been initialized by the initializer list is default constructed.) This is a waste of time because you're just overwriting the values anyway. For small types like int or char this isn't a big deal, but when those member variables are large types that would take lots of cycles to construct, you definitely want to use the initializer list.
The second way won't waste time giving them a default value and then overwriting it - it will set their values directly to that value you give it (or call the right constructor if the member is an object).
You can see what we mean by doing this:
class MyClass {
public:
int _i; // our data
// default constructor
MyClass() : _i(0) { cout << "default constructor"; }
// constructor that takes an int
MyClass(int i) : _i(i) { cout << "int constructor"; }
// assignment operator
void operator=(int i) { _i = i; cout << "assignment operator"; }
};
class OtherClass {
public:
MyClass c;
OtherClass() {
c = 54;
}
};
OtherClass oc;
You'll see that
default constructor
assignment operator
is printed. That's two function calls which, for other classes, could be expensive.
If you change the constructor of OtherClass to
OtherClass() : c(54) { }
You'll see that
int constructor
is printed. Just one call compared to two. This is the most efficient way.
Initializer lists are also a must when you
have types that have no default constructor. You have to call the right constructor in the initializer list.
have a const member that you want to give some value (rather than just have permantently the default value
have a reference member. You must use initializer lists on these.
tl;dr: do it because it's at least as fast but never slower than the other way, and sometimes far faster.
1 For built in types like int and char, they are actually not constructed at all; they just have the value of whatever memory they happen to have had previously.
The difference is that the compiler will always initialize all members (in declaration order) prior to the first user-defined constructor statement. In the case of a char and an int, which are both primitive types, 'initialization' actually means 'no initialization' here. However, if you have a member with a constructor that does some actual work, this constructor will be called upfront - if you do
foo::foo() {
myComplexMember = MyComplexClass(42);
}
the compiler did already invoke the MyComplexClass default constructor before your code got called, which is a waste of resources (and a compiler error if the default ctor is not accessible).
By using an initialization list, you can customize the default initialization and avoid doing things for nothing. Obviously, this is the way to go.
There are things you can do like that that you couldn't otherwise.
If one of the members doesn't have a default constructor. That's the only way you could initiate the member at construction. (same goes to base class)
You can assign a value to a const member.
You can assure a defined state for the class before the constructor function starts running.
If a member is a reference it needs to be initialized in the Initialization List. Because references are immutable and can be initialized only once in the beginning (like const)
Well, this is a typical FAQ question: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6
In your case, using char and int there are no differences.
General rule: use initialization list as possibile, there are very few cases when you can prefer assignment, for example for improve readability:
MyClass::MyClass
{
a = b = c = d = e = f = 0;
}
is better than
class MyClass::MyClass : a(0), b(0), c(0), d(0), e(0), f(0) { }
If the members had non-trivial constructors, in the code below first the default constructors would be called, then the assignments would be executed, while in the code above they would be initialized only one time. So yes, there may be a performance issue.
There is also a practical issue: if they are const, references, or don't have default constructors, you can't use the version below.
There is a subtle, but important difference between those two options. What you have at the top is called a member initialization list. When the object is created, the members in this list are initialized to whatever you put in the parenthesis.
When you do assignment in the constructor body, the values are being first initialized, and then assigned. I'll post a short example below.
Example 1: Member initialization
class foo
{
public:
foo(char c, int i);
private:
char exampleChar;
int exampleInt;
Bar exampleBar;
};
foo::foo(char c, int i):
exampleChar(c),
exampleInt(i),
exampleBar() //Here, a bar is being default constructed
{
}
Example 2: Constructor Assignment
class foo
{
public:
foo(char c, int i, Bar b);
private:
char exampleChar;
int exampleInt;
Bar exampleBar;
};
foo::foo(char c, int i, Bar b):
//exampleChar(c),
//exampleInt(i),
//exampleBar()
{
exampleChar = c;
exampleInt = i;
exampleBar = someOtherBar; //Here, a bar is being assigned
}
This is where it gets interesting. Note that exampleBar is being assigned. Behind the scenes, a Bar is actually first being default constructed, even though you did not specify that. Furthermore, if your Bar is more complicated then a simple struct, you will need to be sure to implement the assignment operator in order for you to initialize it in this way. Even furthermore, in order to initialize the Bar from another Bar from the member initialization list, you must implement the copy constructor!
Example 3: Copy constructor used in member init
class foo
{
public:
foo(char c, int i, Bar b);
private:
char exampleChar;
int exampleInt;
Bar exampleBar;
};
foo::foo(char c, int i, Bar b):
//exampleChar(c),
//exampleInt(i),
exampleBar(b) //Here, a bar is being constructed using the copy constructor of Bar
{
exampleChar = c;
exampleInt = i;
}
I would get into the habit of using initialisation lists. They will not suffer from problems when somebody changes a char to some object where the default constructor is called first, and also for const correctness for the const values!
foo::foo(char c, int i):exampleChar(c),exampleInt(i){}
This construct is called a Member Initializer List in C++.
It initializes your member exampleChar to a value c & exampleInt to i.
What is the difference between Initializing And Assignment inside constructor? &
What is the advantage?
There is a difference between Initializing a member using initializer list and assigning it an value inside the constructor body.
When you initialize fields via initializer list the constructors will be called once.
If you use the assignment then the fields will be first initialized with default constructors and then reassigned (via assignment operator) with actual values.
As you see there is an additional overhead of creation & assignment in the latter, which might be considerable for user defined classes.
For an integer data type(for which you use it) or POD class members there is no practical overhead.