34

I wonder if there is a reason why we can't initialize members at their declaration.

class Foo
{
    int Bar = 42; // this is invalid
};

As an equivalent of using constructor initialization lists.

class Foo
{
    int Bar;
public:
    Foo() : Bar(42) {}
}

My personal understanding is that the above example is much more expressive and intentional. Moreover this is a shorter syntax. And I don't see any possibility of confusion with other language elements.

Is there any official clarification about this?

danijar
  • 32,406
  • 45
  • 166
  • 297
  • 28
    You can in C++11. – chris Mar 16 '13 at 16:42
  • My compiler told me: *"Error: data member initializer is not allowed"*. – danijar Mar 16 '13 at 16:45
  • 2
    So your compiler does not support (all of) C++11 yet. – Arne Mertz Mar 16 '13 at 16:47
  • 1
    Only newer versions of GCC and Clang support it so far. Plus you have to compile in C++11 mode if you aren't. – chris Mar 16 '13 at 16:47
  • Nice to hear that is part of the new standard. Hopefully Visual Studio will support this soon. – danijar Mar 16 '13 at 16:47
  • Yeah, I'm waiting on this for VS as well. They're working hard on finishing what they started in the CTP, though, and that does not include in-class member initialization, so it won't be for a while. – chris Mar 16 '13 at 16:48
  • 1
    I think there's a close enough question of this on SO to dupe. If that can be found, it would usually work better. – chris Mar 16 '13 at 16:49

3 Answers3

30

The initialization of non-static members could not be done like this prior to C++11. If you compile with a C++11 compiler, it should happily accept the code you have given.

I imagine that the reason for not allowing it in the first place is because a data member declaration is not a definition. There is no object being introduced. If you have a data member such as int x;, no int object is created until you actually create an object of the type of the class. Therefore, an initializer on this member would be misleading. It is only during construction that a value can be assigned to the member, which is precisely what member initialization lists are for.

There were also some technical issues to iron out before non-static member initialization could be added. Consider the following examples:

struct S {
    int i(x);
    // ...
    static int x;
};

struct T {
    int i(x);
    // ...
    typedef int x;
};

When these structs are being parsed, at the time of parsing the member i, it is ambiguous whether it is a data member declaration (as in S) or a member function declaration (as in T).

With the added functionality, this is not a problem because you cannot initialize a member with this parantheses syntax. You must use a brace-or-equal-initializer such as:

int i = x;
int i{x};

These can only be data members and so we have no problem any more.

See the proposal N2628 for a more thorough look at the issues that had to be considered when proposing non-static member initializers.

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
  • 1
    At the time `i` is being parsed `x` is unknown, so shouldn't it simply result in compilation error? Traditionally forward declarations were used to resolve such issues. – mip Aug 30 '16 at 03:10
5

The main reason is that initialization applies to an object, or an instance, and in the declaration in the class there is no object or instance; you don't have that until you start constructing.

There's been some evolution in this regard. Already, at the very end of standardization of C++98, the committee added the possibility to do this for static const members of integral type---mainly because these can be used in contexts where the compiler must be able to see the initialization. In C++11, the language has been extended to allow specifying an initializer in the declaration, but this is just a shorthand—the actual initialization still takes place at the top of the constructor.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • 3
    Initialization of data members will also still occur in order of declaration. – Captain Obvlious Mar 16 '13 at 16:59
  • @CaptainObvlious Right, but I guess what James meant was only that the initialisation always occurs during execution of the ctor init list, in the order that members were declared as you said - rather than e.g. being affected by the position of the member declaration relative to the ctor decl/definition. – underscore_d Sep 19 '17 at 18:58
-2

When two or more objects(instance of the class) are declared, those objects share these data members. so value can be initialized with the help of constructor. so we can't initialize the class members during declaration.

YetAnotherBot
  • 1,937
  • 2
  • 25
  • 32