There are two ways construct a class:
class Cell{
public:
Cell(int cellID, int nx);
~Cell();
private:
int cellID_;
int nx;
};
The first way:
Cell::Cell(int cellID, int nx)
: cellID_(cellID), nx_(nx){}
The second way :
Cell::Cell(int cellID, int nx){init(cellID, nx)}
void Cell::init(int cellID, int nx){
cellID_ = cellID;
nx_ = nx;
}
Performance:
The first one is the best because it initializes the objects in true sense unlike second method which assigns the already initialized objects.
Note that there is a little overhead when you use the second method:
As you see there is an additional overhead of creation & assignment in the latter, which might be considerable for user defined classes.
Cost of Member Initialization = Object Construction
Cost of Member Assignment = Object Construction + Assignment
In case of members which are in-built/POD data types there is no overhead but if the members are non POD types then the overhead is significant.
Necessity:
Note that You will be forced to use the member initializer list in certain scenarios:
Your class has a reference member
Your class has a non static const member
Such members cannot be assigned to but they must be initialized in member initializer list.
Given the above as a practice the first method is always preferrable.
The first is nearly always preferred. It's necessary for any members that are references, const or simply require initializers (i.e., can't be default constructed). In other cases, it can reduce extra work by directly initializing the member object instead of default-constructing, then assigning to it afterwards.
In general, initialization lists are better. Check this C++ FAQ.
Should my constructors use "initialization lists" or "assignment"?
Except when you need the below functionality
Can one constructor of a class call another constructor of the same class to initialize the this object?
Related
Let's say I've defined a class containing some simple POD members, and I was too lazy to write out a default constructor to init all the class members to default values. Instead, I asked the compiler to do that for me:
class Foo
{
public:
Foo() = default;
int x;
// etc.
}
I've tested with MSVC, and x is not initialized to zero by this auto-generated constructor: for a local object of class Foo, x was set to 0xcccccccc, which is the value I'd expect for an uninitialized stack variable.
My question is whether there is a standards-compliant way to convince the compiler to zero-init these POD members automatically. I say "standards compliant" because I need to be able to rely on other compilers to behave similarly. And I say "automatically" because I don't want to have to write out a constructor that lists every class member if I can avoid it.
You can use in-class member initializers like this:
class Foo {
int x = 0;;
int y{}; // same effect.
};
The advantage is consistency across constructors that are possibly added later on. This approach is also recommended by the Core Guidelines C.45.
A disadvantage can arise when such a class is declared in a header file, because the type of all member variables that are initialized that way must be known and can't be forward-declared.
Their are two solutions:
Either define a default initializer of the members as in the answer of lubgr which just showed up.
Or always prefer to value initialize your class instances where you could default initialize them: Foo an_obj{}; in place of Foo an_obj;.
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;
};
There are at least two ways to initialize a class in C++.
(1) Initializer List
struct C
{
int i;
C() : i(0) {}
};
(2) Initializer Method
struct D
{
int i;
C() { init(); }
void init() {
i = 0;
}
};
I need to re-init objects of my class from time to time. With the second solution, I can simply call obj.init(). With the first solution, I would either have to add an init() function which essentially duplicates the initializer list effect or use obj = C().
Is there a more-or-less consensus on what variant is better here? Is there a disadvantage to using an initializer method (except the possible loss of performance as mentioned in the C++ FAQ).
The main difference is that without using initialization list, members are created and then values are assigned to them. When you use initialization list, members are directly created by using given values.
One of situations, when using initialization is important, is when your class holds some references as a members and it is necessary to initialize these members right when they are being constructed:
class A
{
public:
A(B& bRef) : bRef_(bRef) { }
private:
B& bRef_;
}
This question could help you too: In this specific case, is there a difference between using a member initializer list and assigning values in a constructor?
Your init() method is perfectly fine. As you yourself have mentioned, you want to initialize these members more times than just first time when the instance of this class is being constructed, so for the sake of reusability and simplicity it's right to keep it in a method. Don't try to improve performance of your code unless you really need it.
Some people say that It's easier to make a correct program fast than it's to make a fast program correct. ;)
When creating an array (using vector, or allocating dynamically using new) you will have to explicitly call init on each of its members while using a constructor, it will automatically be called for all elements.
I prefer placing basic initialization into the constructor and more complex logic into an init method. In my opinion a constructor should not perform any complex operations.
Below are the scenarios when initializer list is used:
For initialization of non-static const data members.
For initialization of reference members.
For initialization of member objects which do not have default constructor.
For initialization of base class members.
When constructor’s parameter name is same as data member.
For Performance reasons.
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.
With respect to the class definition for complex number, I saw two types of definitions:
Definition 1
class Complex
{
private:
double re;
double im;
public:
Complex(float r,float i) {re = r; im = i;}
~Complex() {};
};
Definition 2
class Complex
{
private:
double re;
double im;
public:
Complex(double r,double i): re(r), im(i) {}
~Complex() {};
};
The first definition looks OK to me but I do not quite understand the second definition, how does
Complex(double r,double i): re(r), im(i) {}
work? What does "re( )" mean?
It's called an initializer list. In a class's constructor, you can initialize member variables with this syntax. So in this, it's equivalent to putting the statements re = r; im = i; in the body of the constructor.
In the case of POD variables such as int, double, and pointer types, there is no difference between the initializer list syntax and regular assignments in the body. However, for const variables, references, and objects with non-trivial constructors, there is an important difference:
For const variables and reference variables, they must be initialized in the initializer list. They cannot be initialized by assigning to them in the body.
For objects with non-trivial constructors, how you initialize them in the initializer list corresponds to the constructor that gets called. If you omit the variable, then that object's default constructor gets called (if that object has no default constructor, then that is a compiler error).
Because of that, it's generally recommended that objects with constructors get initialized in the initializer list to avoid redundant work -- if you let its default constructor run by omitting it from the initializer list and then perform some sort of initialization in the constructor body, you're initializing it twice, which can be wasteful.
For example:
class Example
{
private:
std::string m_string;
public:
Example()
{
// m_string is first initialized by the std::string default constructor,
// then we assign to it with operator=(const char *).
// This is inefficient.
m_string = "test";
}
Example(int dummy)
: m_string("test")
{
// Better: we just call the std::string(const char*) constructor directly
}
};
The second form of the Complex constructor uses initialization lists, which are a different (and preferred way) of initialization class members.
The re(...) thing means that member field re should be constructed with whatever arguments it is passed.
As another example - you can create primitives like double and int like this:
double d(5.0d);
int i(5);
Which should explain how the parentheses work in the lists.
That's an initialization list. It sets the value of re to r and the value of im to i.
Generally you'll see a performance gain by using an initialization list, but it's also important to know when not to use it.
First of all, there should be a semicolon after the entire class definition in C++. Otherwise your code will fair to compile.
Anyway, the
Complex(double r,double i): re(r), im(i) {}
is a constructor for the Complex class that simply places the value of r into re and the value of i into im. That is another way of initializing a class's values.
Note that initialization lists like that can be very useful for initializing member classes within a class. Here's an example:
class MemberClass
{
private:
int mValue;
public:
MemberClass(int value): mValue(value) {}
};
class MemberHolder
{
private:
MemberClass mMember;
public:
MemberHolder(int value): mMember(value) {}
};
Initialization lists are important for using classes without a default constructor within other classes.
In C++ there is a distinction between assignment and initialization.
a = 5; // assignment
int b = 6; // initialization
int b(6); // also initialization
The first version of your class performs assignment inside the body of the constructor. This is more expensive, because the data members re and im are first default-constructed, and then are assigned their values.
In the second version constructor initialization list is used. Here the data members are initialized with the supplied values. This occurs in one step, while default constructor + assignment are two steps. This is more efficient.
Generally, you should prefer initializing your data members in the initialization list to assigning their values inside the body of the constructor. There is a caveat, though. The data member in the initialization list are initialized in the order in which they are declared in the class, not in the order in which they occur in the initialization list. Generally, you want the order of members in the list to match their order of declaration. Otherwise you may end up with very hard to find bugs if the initialization of one data member depends on the value of another.