order of object initialization and the use of constructor initializer

Discussion in 'C++' started by Jess, Apr 25, 2007.

  1. Jess

    Jess Guest

    Hello,

    When I define default constructors, I tend to use constructor
    initializers for member data. However, I was told the order in which
    members are initialized is determined by the order of declaration in
    the class, instead of the order they appear in the constructor
    initializer. This would introduce interdependencies. Therefore, it
    is safer to avoid such interdependence by assigning values to these
    members inside the constructor body rather than initializing them in
    the intializer. Could someone explain to me why this is the case?
    Moreover, what kind of error could possibly happen due to the
    "interdependency"?

    Many thanks!
     
    Jess, Apr 25, 2007
    #1
    1. Advertising

  2. Jess wrote:
    > Hello,
    >
    > When I define default constructors, I tend to use constructor
    > initializers for member data. However, I was told the order in which
    > members are initialized is determined by the order of declaration in
    > the class, instead of the order they appear in the constructor
    > initializer. This would introduce interdependencies. Therefore, it
    > is safer to avoid such interdependence by assigning values to these
    > members inside the constructor body rather than initializing them in
    > the intializer. Could someone explain to me why this is the case?
    > Moreover, what kind of error could possibly happen due to the
    > "interdependency"?


    The order of construction is reversed for destruction. If you have
    multiple constructors for the class, the order of construction is always
    the same, as you said, no matter how the initializers are ordered.

    Some compilers will issue a warning if the initializer list is not
    consistent with the order of member declarations.

    As for issues of interdependencies, I don't think I have ever come
    across a situation where this was a problem.
     
    Gianni Mariani, Apr 25, 2007
    #2
    1. Advertising

  3. In message <>, Jess
    <> writes
    >Hello,
    >
    >When I define default constructors, I tend to use constructor
    >initializers for member data. However, I was told the order in which
    >members are initialized is determined by the order of declaration in
    >the class, instead of the order they appear in the constructor
    >initializer. This would introduce interdependencies. Therefore, it
    >is safer to avoid such interdependence by assigning values to these
    >members inside the constructor body rather than initializing them in
    >the intializer.


    They *still* get initialised in the order of declaration, but using the
    default constructor (provided it exists).

    And you have no choice, if the members don't have a default constructor,
    or their assignment operator is not defined, or it has a different
    effect from the constructor.

    > Could someone explain to me why this is the case?
    >Moreover, what kind of error could possibly happen due to the
    >"interdependency"?
    >
    >Many thanks!
    >


    --
    Richard Herring
     
    Richard Herring, Apr 26, 2007
    #3
  4. Jess

    Jess Guest

    If I have a class like:

    class A{
    int x;
    int y;
    string z;
    B b;
    A () : x(0), y(0) { x = 1;}
    }

    Then if I have a code that is "A a;" then I think the following
    happens:
    -- A() is called
    -- x -> 0, y -> 0
    -- z becomes null string
    -- b is initialized by calling B's constructor
    -- body of A() is entered, and x -> 1.

    Is this right?
    If A() is changed to:
    A () : y(0), x(0) { x = 1;}

    Then will the compiler complain? Thanks

    Jess
     
    Jess, Apr 27, 2007
    #4
  5. Jess wrote:
    > If I have a class like:
    >
    > class A{
    > int x;
    > int y;
    > string z;
    > B b;
    > A () : x(0), y(0) { x = 1;}
    > }
    >
    > Then if I have a code that is "A a;" then I think the following
    > happens:
    > -- A() is called
    > -- x -> 0, y -> 0
    > -- z becomes null string


    ... because that's how the default string c-tor behaves.

    > -- b is initialized by calling B's constructor


    ".. by calling B's _default_ constructor"

    > -- body of A() is entered, and x -> 1.


    1 -> x

    >
    > Is this right?


    Pretty much.

    > If A() is changed to:
    > A () : y(0), x(0) { x = 1;}
    >
    > Then will the compiler complain? Thanks


    I don't know, you need to ask the compiler.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Apr 27, 2007
    #5
  6. On Apr 25, 12:07 pm, Jess <> wrote:
    > When I define default constructors, I tend to use constructor
    > initializers for member data. However, I was told the order in which
    > members are initialized is determined by the order of declaration in
    > the class, instead of the order they appear in the constructor
    > initializer. This would introduce interdependencies. Therefore, it
    > is safer to avoid such interdependence by assigning values to these
    > members inside the constructor body rather than initializing them in
    > the intializer. Could someone explain to me why this is the case?
    > Moreover, what kind of error could possibly happen due to the
    > "interdependency"?


    There are cases where one attribute needs to be passed into a
    superclass constructor or into another attribute's constructor and
    these can cause problems.

    Where you're passing between attributes then you should order them
    correctly in the class definition. Where you have to pass into the
    superclass I've done something like this (heavily abridged):

    // Super's constructor needs an int pointer to use
    class Super { Super( int * ); };

    // We store the int here
    class Holder { int m_attribute; };

    // We can now get the int constructed before Super needs it
    class Sub : Holder, Super { Sub(); };

    // Pass the int to Super
    Sub::Sub()
    : Holder(), Super( &m_attribute ) {}

    As I understand it the order of the super-classes in the definition of
    Sub is important, not the order of the calls in the definition of
    Sub's constructor. This is analogous to the case with the attribute
    order in the class definition.


    K
     
    =?iso-8859-1?q?Kirit_S=E6lensminde?=, Apr 27, 2007
    #6
  7. Jess

    James Kanze Guest

    On Apr 27, 5:11 am, Jess <> wrote:
    > If I have a class like:


    > class A{
    > int x;
    > int y;
    > string z;
    > B b;
    > A () : x(0), y(0) { x = 1;}
    > }


    > Then if I have a code that is "A a;" then I think the following
    > happens:
    > -- A() is called
    > -- x -> 0, y -> 0
    > -- z becomes null string
    > -- b is initialized by calling B's constructor
    > -- body of A() is entered, and x -> 1.


    > Is this right?
    > If A() is changed to:
    > A () : y(0), x(0) { x = 1;}


    > Then will the compiler complain? Thanks


    It might issue a warning, but the code is legal, and does
    exactly what the previous code does.

    The only time this is a problem is if you write something like:

    A::A() : y( 0 ), x( y ) { x = 1; }

    In this case, you actually have undefined behavior, because you
    try to initialize x with y before having initialized y.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Apr 27, 2007
    #7
  8. Jess

    Marcus Kwok Guest

    Jess <> wrote:
    > When I define default constructors, I tend to use constructor
    > initializers for member data. However, I was told the order in which
    > members are initialized is determined by the order of declaration in
    > the class, instead of the order they appear in the constructor
    > initializer. This would introduce interdependencies. Therefore, it
    > is safer to avoid such interdependence by assigning values to these
    > members inside the constructor body rather than initializing them in
    > the intializer. Could someone explain to me why this is the case?
    > Moreover, what kind of error could possibly happen due to the
    > "interdependency"?


    Here is a contrived example, but it demonstrates the point:


    #include <iostream>

    struct Foo {
    const int c;
    int i;

    Foo(int x) : c(x), i(2 * c) { }
    };


    struct Bar {
    int i;
    const int c;

    Bar(int x) : c(x), i(2 * c) { }
    };


    int main()
    {
    using std::cout;

    Foo f(3);
    cout << f.c << ", " << f.i << '\n';

    Bar b(3);
    cout << b.c << ", " << b.i << '\n';
    }


    Output:
    3, 6
    3, 8529120


    In Foo, first the const int c is initialized with the value of 3, then
    the int i is initialized with the value of (2*3).

    In Bar, since i was declared before c, then i's initialization occurs
    first. At this point the value of c is garbage (and thus reading it is
    really undefined behavior), so i is initialized with 2*garbage before c
    is initialized.

    --
    Marcus Kwok
    Replace 'invalid' with 'net' to reply
     
    Marcus Kwok, Apr 27, 2007
    #8
  9. Jess

    Jess Guest

    Many thanks for your explanations!

    Jess
     
    Jess, Apr 28, 2007
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alexander Stippler
    Replies:
    3
    Views:
    445
    Leor Zolman
    Apr 9, 2004
  2. Chris K
    Replies:
    1
    Views:
    580
    Victor Bazarov
    Apr 17, 2004
  3. Vincent RICHOMME

    constructor and initializer

    Vincent RICHOMME, Jan 14, 2006, in forum: C++
    Replies:
    1
    Views:
    297
  4. Generic Usenet Account
    Replies:
    10
    Views:
    2,289
  5. balaji
    Replies:
    3
    Views:
    957
    Jens Thoms Toerring
    Aug 10, 2011
Loading...

Share This Page