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.
Related
I want to declare two objects from two different classes inside my private section of my class. The problem I have is that the second object should take the first object in a constructor. So here is the example of my class private section:
class FactorGraph
{
private:
gtsam::ISAM2Params _parameters();
gtsam::ISAM2 _isam(_parameters);
The _parameters object should be passed as an argument for the _isam object but from my knowledge that will not be possible as C++ does not allow this. Is there a slick way to do so?
Initialize your second object in the constructor (or better both):
FactorGraph::FactorGraph()
: _parameters{}, _isam{_parameters}
{ }
The initialization happens in the same order in which the members are listed in your class (regardless of the order of this list(!), so it's a good idea to keep the same order here, your compiler may even warn you otherwise), which here guarantees that _isam won't get anything uninitialized. (I'm not aware of such guarantees if you just define your objects in your class declaration.)
From the comments, thanks #drescherjm: In your class, just declare your objects without initializers:
class FactorGraph
{
private:
gtsam::ISAM2Params _parameters;
gtsam::ISAM2 _isam;
When you declare them without initializers, they should be initialized in the constructor instead. They do not need to be default-constructible in order to do this, the objects gets initialized only once (in the constructor)
Then if you have more constructors, don't forget to either do that everywhere or forward to this one:
FactorGraph(int) : FactorGraph{}, /* other initializers */ { }
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 many C++ programming best practices that are proposed in many articles and books. Following is a subset that is related to C++ class data members:
Make sure that objects are initialized before they are used.
Make sure that all constructors initialize everything in the object.
It is usually more effective to initialize data members in the initializer list of each constructor than in its body.
In the initializer list, data members should be listed in the order they are declared.
Consider the following class with data members of Qt class types:
class MyClass {
public:
myClass();
~myClass();
private:
int myInt;
QString myQString;
QList<QString> myQList;
QHash<int, QString> myQHash;
char * pChar;
};
By applying the above best practices, the constructor code would look like the following:
MyClass::MyClass() :
myInt(0), // OK, primitive should be initialized.
myQString(), // Is this really needed?
myQList(), // Is this really needed?
myQHash(), // Is this really needed?
pChar(NULL) // OK, pointer should be initialized.
{
}
However, I have the impression that not all of the Qt class data members need to be initialized. But I am not 100 % sure of this. Some developers argue that by putting all the data members in the initialization list, we may avoid omitting the initialization of some important data members that should be initialized. However, if this is a real concern, I would prefer putting a comment line for each data member that does not need to be initialized, for example:
MyClass::MyClass() :
myInt(0),
//myQString(),
//myQList(),
//myQHash(),
pChar(NULL)
{
}
To summarize, I would like to know when a Qt class data member should be initialized, and when the initialization is not needed, and why. Thanks!
If you don't have a default constructor of a class then you must initialize it in initializer list, and it is not required to call default constructor in initializer list. It is not Qt specific it is a general rule for any class. When you have a default constructor(which takes 0 argument) even if you don't call it in initializer list, it will be called automatically.
Update:
Q1: Are the 2 versions of MyClass::MyClass() above equivalent? That
is, do they produce 2 objects of same content?
Yes.
Q2: Is one version faster than the other?
You can type the second version faster ;-), there is no performance difference.
Default constructor of QObject's will be called regardless you call it explicitly, or it's called implicitly when your object is created.
You may put a debug message into QObject constructor code and see for yourself, it's Open Source for truth's sake! :)
I am writing the following classes in C++.
class SImage {
...
public:
SImage(char*);
}
class SImageProc {
SImage S;
...
public:
SImageProc(SImage Im) { S = Im; };
}
When compiling I receive this referencing the line where I implement my constructor:
SImageProc.cpp:5:33: error: no matching function for call to 'SImage::SImage()'
I cannot figure out why it is interpreting my parameters as instantions of a class when implementing the SImageProc class.
SImage does not have a default constructor, because you have provided constructor SImage(char*). This means the compiler no longer provides a default one. Something elsewhere in your code requires SImage, causing the error.
You need to provide a default constructor for SImage, or remove the code that requires it. It is not possible to say which one of the solutions is suitable without more details.
My wild guess would be that SImageProc has an SImage data member, and you are not initializing it in the constructor initialization list. This is how you would fix that problem:
SImageProc(SImage Im) : S(Im) {};
The explanation for that is that, by the time you reach a constructor's body, all data members and bases have been initialized. After initialization you can only modify them (in your example, you were assigning to S.) If you do not explicitly initialize data members and bases in the constructor initialization list, they (usually) get default initialized, which in the case of a user defined type means the default constructor is called. This is the source of the error.
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?