views:

288

answers:

1

So, the C++ standard requires that class members be initialized in the order in which they are declared in the class, rather than the order that they're mentioned in any constructor's initializer list. However, this doesn't imply anything about the order in which the arguments to those initializations are evaluated. I'm working with a system that frequently passes references to serialization objects around, and wondering if I can ensure that bits are read from it in the right order, independent of the order in which those bits get written into the object's fields.

struct Foo {
    int a;
    double b;
    // I want to be able to do this
    Foo(SerObj &s)
    : b(s.readDouble()), a(s.readInt())
    { }
    // Rather than this
    Foo (SerObj &s)
    {
        b = s.readDouble();
        a = s.readInt();
    }
};

Obviously, reordering things like ints and doubles in the declaration is not too big a deal, but bigger objects and things requiring dynamic allocation sometimes can be.

+9  A: 

C++ Standard 12.6.2/3:

There is a sequence point (1.9) after the initialization of each base and member. The expression-list of a mem-initializer is evaluated as part of the initialization of the corresponding base or member.

The order of the initialization is the one you specified in the question. Evaluation is part of this initialization, and the initializations can't interleave (because there is a sequence point between them).

That means that the function calls in your initializer lists are not called in the desired order, but in the order in which the member declarations appear.

Johannes Schaub - litb
Could you please add a link to the source? Thanks.
Jon Seigel
Sorry if i misread, but wasn't the question about the evaluation order of the arguments to the member constructors in their respective initialization? Which should be undefined?
Georg Fritzsche
Hm, probably not as there is only one argument respectively.
Georg Fritzsche
Yes, the evaluation order of arguments to a member constructor is unspecified, and there is no sequence point between them. @Jon Seigel, the Standard is not publicly available. But here is `12.6.2` in a public draft from 1998: http://www.kuzbass.ru:8086/docs/isocpp/special.html#class.base.init
Johannes Schaub - litb
Thanks. Too bad there's no way to separate evaluation order from initialization order.
Novelocrat
Note that in C++0x, there are no sequence points anymore. But instead, C++0x just emphasizes that each member/base initialization constitutes a full-expression (implicit constructor function call), and the expression appearing in the initialization is associated with that full expression. (And each evaluation in a full-expression in C++0x is sequenced-before the next full-expression to be evaluated, which will forbid interleaving likewise). So you will find different wording if you look in a C++0x draft :)
Johannes Schaub - litb