Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can member variables be used to initialize other members in an initialization list?

Consider the following (simplified) situation:

class Foo { private:     int evenA;     int evenB;     int evenSum; public:     Foo(int a, int b) : evenA(a-(a%2)), evenB(b-(b%2)), evenSum(evenA+evenB)     {     } }; 

When i instanciate Foo like this:

Foo foo(1,3); 

then evenA is 0, evenB is 2, but will evenSum be initialized to 2?

I tried this on my current platform (iOS) and it seems to work, but I'm not sure whether this code is portable.

Thanks for your help!

like image 217
Pontomedon Avatar asked May 23 '12 12:05

Pontomedon


People also ask

Should member variables be initialized?

You should always initialize native variables, especially if they are class member variables. Class variables, on the other hand, should have a constructor defined that will initialize its state properly, so you do not always have to initialize them.

Should all member variables be initialized in __ init __?

If the value is not arbitrary and simply a default value that can be changed you should be using a default value in the __init__ method that can be overridden. It can also actually be a valid initial state, which is also not arbitrary and you should set it in the __init__ method.

What is member initializer list?

Member initializer list is the place where non-default initialization of these objects can be specified. For bases and non-static data members that cannot be default-initialized, such as members of reference and const-qualified types, member initializers must be specified.

Can we initialize member variable in class in C++?

Static Data Member Initialization in C++We can put static members (Functions or Variables) in C++ classes. For the static variables, we have to initialize them after defining the class. To initialize we have to use the class name then scope resolution operator, then the variable name.


2 Answers

This is well-defined and portable,1 but it's potentially error-prone.

Members are initialized in the order they're declared in the class body, not the order they're listed in the initialization list. So if you change the class body, this code may silently fail (although many compilers will spot this and emit a warning).


1. From [class.base.init] in the C++ standard(s):

In a non-delegating constructor, initialization proceeds in the following order:

  • First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
  • Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
  • Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
  • Finally, the compound-statement of the constructor body is executed.

(Highlighting is mine.)

This section of the standard then goes on to give an example of using member variables to initialize other member variables.

like image 180
Oliver Charlesworth Avatar answered Sep 19 '22 03:09

Oliver Charlesworth


Yes, provide they've already been constructed. Just don't forget that the order of construction is the order of the declarations in the class definition, not the order of the initializers in the constructor. And that the compiler typically won't tell you if you use a variable before it has been constructed. In your case, for example, if you move evenSum to the top of the class, you have undefined behavior (because its initializer uses uninitialized members), even though in your constructor, you initialize evenA and evenB lexically before evenSum.

like image 25
James Kanze Avatar answered Sep 18 '22 03:09

James Kanze