2

Consider the following class definition:

class C {
public:
    int i = 9;
    const int j = 2;
};

Without using the flag to enable C++11 when compiling (using g++, e.g. g++ -o test test.cpp) the compiler complains on the member variable initializations. However, using -std=c++11 this works fine.

Why has this rule been changed in C++11? Is it considered bad practice initializing member variables in this manner?

Rapptz
  • 20,807
  • 5
  • 72
  • 86
jensa
  • 2,792
  • 2
  • 21
  • 36
  • 7
    It was changed because it is very convenient to be able to do that. – juanchopanza Sep 10 '14 at 19:39
  • Ok, so typing int i = 9;, would be equivalent to typing int i; and then in the constructor typing i = 9; ? – jensa Sep 10 '14 at 19:40
  • No, it would be equal to initializing in member initialization list. `i = 9;` in the body of a constructor is assignment, not initialization. – jrok Sep 10 '14 at 19:42
  • Ok, so it is first initialized (to zero I guess, the default value for integers), and then the body of the constructor executes and i gets assigned the value 9 ? – jensa Sep 10 '14 at 19:47
  • There is no such thing as default values for data members. – fredoverflow Sep 10 '14 at 19:47
  • @jensa: Why should it be zero-initialized first? – Deduplicator Sep 10 '14 at 19:47
  • @Deduplicator: Initialization is not required before assignment? – jensa Sep 10 '14 at 19:51
  • There are 3 different initialization-concepts in the standard: default-initialization, value-initialization and zero-initialization. Default-initialization equals no-initialization in many cases. – Deduplicator Sep 10 '14 at 19:53
  • Okay thanks. No-initialization leaves us with an undefined value? – jensa Sep 10 '14 at 19:57
  • http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2628.html talks about the in-class member initializer syntax. It might have the answer you are looking for. – R Sahu Sep 10 '14 at 20:17
  • @jensa constructor initializer lists do initialization, not assignment. They specify the initial values for data members and base classes. Reading a variable before it was initialized (which is possible) causes undefined behaviour. – M.M Sep 10 '14 at 20:36

1 Answers1

4

Initializing non-static data members at the point of their declaration wasn't just "bad practice"; it simply wasn't possible at all prior to C++11.

The equivalent C++03 code would be:

class C
{
public:

    C() : i(9), j(2)
    {
    }

    int i;
    const int j;
};

And just in case: What is this weird colon-member syntax in the constructor?

Community
  • 1
  • 1
fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • the relevant section of the standard would be? – Mgetz Sep 10 '14 at 19:43
  • 3
    @Mgetz The standard doesn't have a section for each non-existing language feature. – fredoverflow Sep 10 '14 at 19:44
  • Note that even in C++11, member initializer (in constructor, if there is one) overrides the one from the member declaration. – jrok Sep 10 '14 at 19:45
  • 1
    Isn't the question "Why was it changed?" Instead of "Might you re-iterate my observations?" or "How would that be done pre-C++11?"? – Deduplicator Sep 10 '14 at 19:45
  • Although that is the equivalent, I'd like to note to newbies that you really, really, really **always** want to make your member variables private, and perhaps protected if you know what you're doing (but not "just because"). The reason for this is that code with public member variables violates the whole principle of Object Oriented, resulting quickly in unmaintainable code and bugs. Especially when a code base becomes large you NEED them to be non-accessible from the outside to have any benefit from using C++. – Carlo Wood Sep 10 '14 at 19:48
  • Thanks, I've understood that C() : i(9), j(2) will initialize the member variables to 9 and 2, respectively. And if we had done int i = 15;, the value 15 would have been overriden with 9. – jensa Sep 10 '14 at 19:49
  • 5
    @CarloWood: Public member-variables do not neccessarily violate proper encapsulation (and encapsulation is not always called for at all), though your rule leads to massive doses (maybe even lethal) of faux-encapsulation. Please abstain. – Deduplicator Sep 10 '14 at 19:51
  • @CarloWood Also, don't forget getters and setters for ALL THE MEMBERS! :) – jrok Sep 10 '14 at 19:52
  • There's not much difference between a public member var, and a private var with public setter and getter. It's just a hack so that you can change the semantics of the object later by hooking those operations. Changing semantics of an object counts as changing the interface though! – M.M Sep 10 '14 at 20:38