Member initialisation and construction

Discussion in 'C++' started by Taras_96, Oct 20, 2009.

  1. Taras_96

    Taras_96 Guest

    Hi all,

    I'm trying to determine which members get intialised by default and
    which don't when we consider both constructors and copy constructors.
    Essentially I have the following matrix (I abbreviate Bjarne
    Stroustrup's C++ book as 'TCPL' below)

    Constructor:
    Compiler generated default
    UDTs – default initialised – page 243 of TCPL
    Built in – not default initialised – page 244 of TCPL
    User generated
    UDTs – default initialised – page 248 of TCPL (the example shows a
    UDT of a user generated constructor being default initialised)
    Built in - not sure about this
    Copy constructor
    Compiler generated default
    UDTs - not sure about this - would they be copied using the UDT's
    copy constructor?
    Built in - not sure about this
    User generated
    UDTs – default initialised – page 250 of TCPL
    Built in - not sure about this

    Can anyone fill in the missing entries? ;)

    Taras
    Taras_96, Oct 20, 2009
    #1
    1. Advertising

  2. On Oct 20, 8:55 am, Taras_96 <> wrote:
    > Hi all,
    >
    > I'm trying to determine which members get intialised by default and
    > which don't when we consider both constructors and copy constructors.
    > Essentially I have the following matrix (I abbreviate Bjarne
    > Stroustrup's C++ book as 'TCPL' below)
    >
    > Constructor:
    >         Compiler generated default
    >                 UDTs – default initialised – page 243 of TCPL
    >                 Built in – not default initialised – page 244 of TCPL
    >         User generated
    >                 UDTs – default initialised – page 248 of TCPL (the example shows a
    > UDT of a  user generated constructor being default initialised)
    >                 Built in - not sure about this
    > Copy constructor
    >         Compiler generated default
    >                 UDTs - not sure about this - would they be copied using the UDT's
    > copy constructor?
    >                 Built in - not sure about this
    >         User generated
    >                 UDTs – default initialised – page 250 of TCPL
    >                 Built in - not sure about this
    >
    > Can anyone fill in the missing entries? ;)
    >
    > Taras


    First, the distinction you make between User-Defined types and built-
    in types does not cover all cases. There are a number of user-defined
    types (such as simple structures of built-in types) that act similar
    to a built-in type in your table.

    A better distinction is if your members have a trivial or non-trivial
    consctructor.
    If a type or one of its (indirect) members or baseclasses has a user-
    defined constructor, then the type has a non-trivial constructor. All
    other types have have a non-trivial constructor.

    With this distinction, your table becomes:
    default constructor:
    compiler-generated default:
    non-trivial constructor: default constructor is called
    trivial constructor: member is left uninitialised
    user generated:
    non-trivial constructor: if mentioned in the initialiser-list, the
    corresponding constructor is called; otherwise the default constructor
    is called
    trivial constructor: if the member is mentioned in the initialiser-
    list, it is initialised; otherwise the member is left uninitialised
    copy-constructor:
    compiler-generated default:
    non-trivial constructor: copy-constructor is called
    trivial constructor: member is copied
    user generated:
    non-trivial constructor: if mentioned in the initialiser-list, the
    corresponding constructor is called; otherwise the default constructor
    is called
    trivial constructor: if the member is mentioned in the initialiser-
    list, it is initialised; otherwise the member is left uninitialised

    Bart v Ingen Schenau
    Bart van Ingen Schenau, Oct 20, 2009
    #2
    1. Advertising

  3. Taras_96

    Taras_96 Guest

    All of that makes perfect sense.. thanks Bart!
    Taras_96, Oct 22, 2009
    #3
  4. Taras_96

    Taras_96 Guest

    On Oct 20, 7:27 pm, Bart van Ingen Schenau <>
    wrote:
    > On Oct 20, 8:55 am, Taras_96 <> wrote:


    >   compiler-generated default:
    >     non-trivial constructor: copy-constructor is called
    >     trivial constructor: member is copied
    >   user generated:
    >     non-trivial constructor: if mentioned in the initialiser-list, the
    > corresponding constructor is called; otherwise the default constructor
    > is called
    >     trivial constructor: if the member is mentioned in the initialiser-
    > list, it is initialised; otherwise the member is left uninitialised
    >
    > Bart v Ingen Schenau


    Does this mean if you have the following classes:

    class A{};

    class B
    {
    private:
    A a;
    public:
    B(const & rhs){}
    }

    Then the member 'a' would be left unitialised, even though it is a
    UDT?

    Taras
    Taras_96, Oct 22, 2009
    #4
  5. Taras_96 wrote:
    > On Oct 20, 7:27 pm, Bart van Ingen Schenau <>
    > wrote:
    >> On Oct 20, 8:55 am, Taras_96 <> wrote:

    >
    >> compiler-generated default:
    >> non-trivial constructor: copy-constructor is called
    >> trivial constructor: member is copied
    >> user generated:
    >> non-trivial constructor: if mentioned in the initialiser-list, the
    >> corresponding constructor is called; otherwise the default constructor
    >> is called
    >> trivial constructor: if the member is mentioned in the initialiser-
    >> list, it is initialised; otherwise the member is left uninitialised
    >>
    >> Bart v Ingen Schenau

    >
    > Does this mean if you have the following classes:
    >
    > class A{};
    >
    > class B
    > {
    > private:
    > A a;
    > public:
    > B(const & rhs){}
    > }
    >
    > Then the member 'a' would be left unitialised, even though it is a
    > UDT?


    First off, your code has no semicolon after the definition of 'B' and
    the argument in B's c-tor has no type. If that's fixed, then the rule
    is simple: any data member omitted from the initialiser list, shall be
    value-initialised ([class.base.init]/3), not *un*initialised. UDT or
    not does not matter. Value-initialisation is performed differently for
    POD than for non-POD, but that does not change the fact that an omitted
    member is value-initialised.

    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, Oct 22, 2009
    #5
  6. Taras_96

    Taras_96 Guest

    On Oct 22, 11:59 pm, Victor Bazarov <> wrote:
    > Taras_96 wrote:
    > > On Oct 20, 7:27 pm, Bart van Ingen Schenau <>
    > > wrote:
    > >> On Oct 20, 8:55 am, Taras_96 <> wrote:

    >
    > >>   compiler-generated default:
    > >>     non-trivial constructor: copy-constructor is called
    > >>     trivial constructor: member is copied
    > >>   user generated:
    > >>     non-trivial constructor: if mentioned in the initialiser-list, the
    > >> corresponding constructor is called; otherwise the default constructor
    > >> is called
    > >>     trivial constructor: if the member is mentioned in the initialiser-
    > >> list, it is initialised; otherwise the member is left uninitialised

    >
    > >> Bart v Ingen Schenau

    >
    > > Does this mean if you have the following classes:

    >
    > > class A{};

    >
    > > class B
    > > {
    > >   private:
    > >     A a;
    > >   public:
    > >     B(const & rhs){}
    > > }

    >
    > > Then the member 'a' would be left unitialised, even though it is a
    > > UDT?

    >
    > First off, your code has no semicolon after the definition of 'B' and
    > the argument in B's c-tor has no type.  If that's fixed, then the rule
    > is simple: any data member omitted from the initialiser list, shall be
    > value-initialised ([class.base.init]/3), not *un*initialised.  UDT or
    > not does not matter.  Value-initialisation is performed differently for
    > POD than for non-POD, but that does not change the fact that an omitted
    > member is value-initialised.
    >
    > V
    > --


    I might be reading an old copy of the standard, but the version I'm
    reading (http://www.kuzbass.ru:8086/docs/isocpp) states:

    class.base.init/3:

    "The expression-list in a mem-initializer is used to initialize the
    base class or nonstatic data member subobject denoted by the mem-
    initializer-id. The semantics of a mem-initializer are as follows:
    * if the expression-list of the mem-initializer is omitted, the
    base class or member subobject is default-initialized (see dcl.init);
    * otherwise, the subobject indicated by mem-initializer-id is
    direct-initialized using expression-list as the initializer (see
    dcl.init). "

    So this means that:

    class Bar
    {
    public:
    ~Bar() {}; // so that Bar is not POD
    };

    class Foo
    {
    private:
    int x;
    Bar bar;
    public:
    Foo();
    ~Foo() {};
    };

    Foo::Foo():
    x(), // default initialised
    bar() // default initialised
    {}


    class.base.init/4 states that:

    "-4- If a given nonstatic data member or base class is not named by a
    mem-initializer-id (including the case where there is no mem-
    initializer-list because the constructor has no ctor-initializer),
    then

    * If the entity is a nonstatic data member of (possibly cv-
    qualified) class type (or array thereof) or a base class, and the
    entity class is a non-POD class, the entity is default-initialized
    (dcl.init). If the entity is a nonstatic data member of a const-
    qualified type, the entity class shall have a user-declared default
    constructor.

    * Otherwise, the entity is not initialized. If the entity is of
    const-qualified type or reference type, or of a (possibly cv-
    qualified) POD class type (or array thereof) containing (directly or
    indirectly) a member of a const-qualified type, the program is ill-
    formed. "

    This means that if we changed the above Foo constructor to:

    Foo::Foo() {};

    Then Foo::bar would be default initialised whereas Foo::x would be
    left uninitialised

    So what about implicit constructors?

    class.ctor.

    "-5- A default constructor for a class X is a constructor of class X
    that can be called without an argument. If there is no user-declared
    constructor for class X, a default constructor is implicitly declared.
    An implicitly-declared default constructor is an inline public member
    of its class. A constructor is trivial if it is an implicitly-declared
    default constructor and if: ...."

    "-7- An implicitly-declared default constructor for a class is
    implicitly defined when it is used to create an object of its class
    type (intro.object). The implicitly-defined default constructor
    performs the set of initializations of the class that would be
    performed by a user-written default constructor for that class with an
    empty mem-initializer-list (class.base.init) and an empty function
    body"

    So the implicitly-declared default constructor for Foo would be the
    same as the Foo constructor declared above... x would be
    uninitialised, and bar would be default initialised.

    Interestingly there is no mention of the constructor being trivial or
    not.

    Now what about copy constructors? First consider the implicitly
    defined copy constructor...

    class.copy

    -8- The implicitly-defined copy constructor for class X performs a
    memberwise copy of its subobjects. The order of copying is the same as
    the order of initialization of bases and members in a user-defined
    constructor (see class.base.init). Each subobject is copied in the
    manner appropriate to its type:

    * if the subobject is of class type, the copy constructor for the
    class is used;

    * if the subobject is an array, each element is copied, in the
    manner appropriate to the element type;

    * if the subobject is of scalar type, the built-in assignment
    operator is used.

    Virtual base class subobjects shall be copied only once by the
    implicitly-defined copy constructor (see class.base.init).

    What about copy constructors that do no list all members in the member
    initialization list?

    I believe this would fall under class.base.init/4, where an integer
    member would be left unitialised.

    However, this doesn't agree with what you stated...?

    Taras
    Taras_96, Oct 23, 2009
    #6
  7. Taras_96 wrote:
    > On Oct 22, 11:59 pm, Victor Bazarov <> wrote:
    >> Taras_96 wrote:
    >>> On Oct 20, 7:27 pm, Bart van Ingen Schenau <>
    >>> wrote:
    >>>> On Oct 20, 8:55 am, Taras_96 <> wrote:
    >>>> compiler-generated default:
    >>>> non-trivial constructor: copy-constructor is called
    >>>> trivial constructor: member is copied
    >>>> user generated:
    >>>> non-trivial constructor: if mentioned in the initialiser-list, the
    >>>> corresponding constructor is called; otherwise the default constructor
    >>>> is called
    >>>> trivial constructor: if the member is mentioned in the initialiser-
    >>>> list, it is initialised; otherwise the member is left uninitialised
    >>>> Bart v Ingen Schenau
    >>> Does this mean if you have the following classes:
    >>> class A{};
    >>> class B
    >>> {
    >>> private:
    >>> A a;
    >>> public:
    >>> B(const & rhs){}
    >>> }
    >>> Then the member 'a' would be left unitialised, even though it is a
    >>> UDT?

    >> First off, your code has no semicolon after the definition of 'B' and
    >> the argument in B's c-tor has no type. If that's fixed, then the rule
    >> is simple: any data member omitted from the initialiser list, shall be
    >> value-initialised ([class.base.init]/3), not *un*initialised. UDT or
    >> not does not matter. Value-initialisation is performed differently for
    >> POD than for non-POD, but that does not change the fact that an omitted
    >> member is value-initialised.
    >>
    >> V
    >> --

    >
    > I might be reading an old copy of the standard, but the version I'm
    > reading (http://www.kuzbass.ru:8086/docs/isocpp) states:
    >
    > [.."final draft" of 1998 standard quoted..]


    It must be different from the currently active language standard. Get
    yourself a copy and check. I vaguely remember that there were some
    changes made to initialization clause. Also, look in the archives for
    posts from Andrew Koenig on "value-initialization", you will most likely
    find that the initialization was reworked/reworded.

    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, Oct 23, 2009
    #7
  8. Taras_96

    Taras_96 Guest

    On Oct 24, 9:55 am, Victor Bazarov <> wrote:
    > Taras_96 wrote:
    > > On Oct 22, 11:59 pm, Victor Bazarov <> wrote:
    > >> Taras_96 wrote:
    > >>> On Oct 20, 7:27 pm, Bart van Ingen Schenau <>
    > >>> wrote:
    > >>>> On Oct 20, 8:55 am, Taras_96 <> wrote:
    > >>>>   compiler-generated default:
    > >>>>     non-trivial constructor: copy-constructor is called
    > >>>>     trivial constructor: member is copied
    > >>>>   user generated:
    > >>>>     non-trivial constructor: if mentioned in the initialiser-list, the
    > >>>> corresponding constructor is called; otherwise the default constructor
    > >>>> is called
    > >>>>     trivial constructor: if the member is mentioned in the initialiser-
    > >>>> list, it is initialised; otherwise the member is left uninitialised
    > >>>> Bart v Ingen Schenau
    > >>> Does this mean if you have the following classes:
    > >>> class A{};
    > >>> class B
    > >>> {
    > >>>   private:
    > >>>     A a;
    > >>>   public:
    > >>>     B(const & rhs){}
    > >>> }
    > >>> Then the member 'a' would be left unitialised, even though it is a
    > >>> UDT?
    > >> First off, your code has no semicolon after the definition of 'B' and
    > >> the argument in B's c-tor has no type.  If that's fixed, then the rule
    > >> is simple: any data member omitted from the initialiser list, shall be
    > >> value-initialised ([class.base.init]/3), not *un*initialised.  UDT or
    > >> not does not matter.  Value-initialisation is performed differently for
    > >> POD than for non-POD, but that does not change the fact that an omitted
    > >> member is value-initialised.

    >
    > >> V
    > >> --

    >
    > > I might be reading an old copy of the standard, but the version I'm
    > > reading (http://www.kuzbass.ru:8086/docs/isocpp) states:

    >
    > > [.."final draft" of 1998 standard quoted..]

    >
    > It must be different from the currently active language standard.  Get
    > yourself a copy and check.  I vaguely remember that there were some
    > changes made to initialization clause.  Also, look in the archives for
    > posts from Andrew Koenig on "value-initialization", you will most likely
    > find that the initialization was reworked/reworded.
    >
    > V
    > --
    > Please remove capital 'A's when replying by e-mail
    > I do not respond to top-posted replies, please don't ask


    I got the active standard, ISO/IEC 14882:2003(E), and still couldn't
    find anywhere that stated what you mentioned:

    "then the rule is simple: any data member omitted from the initialiser
    list, shall be
    value-initialised ([class.base.init]/3), not *un*initialised. UDT or
    not does not matter. Value-initialisation is performed differently
    for
    POD than for non-POD, but that does not change the fact that an
    omitted
    member is value-initialised."

    class.base.init/3 stated:

    "— if the expression-list of the mem-initializer is omitted, the base
    class or member subobject is value initialized (see 8.5);
    — otherwise, the subobject indicated by mem-initializer-id is direct-
    initialized using expression-list as the initializer (see 8.5)."

    This is concerned with not the mem-initializer-id being absent, but
    rather the expression-list being absent.

    class.base.init/4 states:

    "— If the entity is a nonstatic data member of (possibly cv-qualified)
    class type (or array thereof) or a base
    class, and the entity class is a non-POD class, the entity is default-
    initialized (8.5). If the entity is a nonstatic
    data member of a const-qualified type, the entity class shall have a
    user-declared default constructor.
    — Otherwise, the entity is not initialized. If the entity is of const-
    qualified type or reference type, or of a
    (possibly cv-qualified) POD class type (or array thereof) containing
    (directly or indirectly) a member of
    a const-qualified type, the program is ill-formed."

    So Foo::x will be unitialized if it is left out in the initialisation
    list (and not assigned a value in the body of the constructor).

    My interpretation of default versus value initialisation is that the
    only difference is that default initialisation calls the default
    constructor regardless of whether the ctor is user defined or not,
    whereas value-initialisation only calls the default constructor if it
    was user defined, otherwise it value-intialises the member.

    The standard states that:

    "The object is default-initialized if there is no initializer, or
    value-initialized if the initializer is ()."

    So using the example:

    class Foo
    {
    private:
    int x;
    public:
    ~Foo() {};

    };

    If we write:

    Foo x; // default-initialisation

    Then the (compiler-generated) constructor will be called, which is
    equivalent to an empty constructor with an empty initializer list, so
    Foo::x will remain uniitialized.

    However,

    Foo x() // value-initialisation

    Then, as there is no user-defined constructor, the members of x will
    be value-initialised, which means that Foo::x will be zero
    initialised!

    Is this correct?

    I'm still unsure of what happens if you do not initialise a data
    member in the copy constructor, but I think the above needs to be
    sorted first.

    Taras
    Taras_96, Oct 26, 2009
    #8
  9. Taras_96

    Pavel Guest

    Taras_96 wrote:
    > On Oct 24, 9:55 am, Victor Bazarov <> wrote:
    >> Taras_96 wrote:
    >>> On Oct 22, 11:59 pm, Victor Bazarov <> wrote:
    >>>> Taras_96 wrote:
    >>>>> On Oct 20, 7:27 pm, Bart van Ingen Schenau <>
    >>>>> wrote:
    >>>>>> On Oct 20, 8:55 am, Taras_96 <> wrote:
    >>>>>> compiler-generated default:
    >>>>>> non-trivial constructor: copy-constructor is called
    >>>>>> trivial constructor: member is copied
    >>>>>> user generated:
    >>>>>> non-trivial constructor: if mentioned in the initialiser-list, the
    >>>>>> corresponding constructor is called; otherwise the default constructor
    >>>>>> is called
    >>>>>> trivial constructor: if the member is mentioned in the initialiser-
    >>>>>> list, it is initialised; otherwise the member is left uninitialised
    >>>>>> Bart v Ingen Schenau
    >>>>> Does this mean if you have the following classes:
    >>>>> class A{};
    >>>>> class B
    >>>>> {
    >>>>> private:
    >>>>> A a;
    >>>>> public:
    >>>>> B(const & rhs){}
    >>>>> }
    >>>>> Then the member 'a' would be left unitialised, even though it is a
    >>>>> UDT?
    >>>> First off, your code has no semicolon after the definition of 'B' and
    >>>> the argument in B's c-tor has no type. If that's fixed, then the rule
    >>>> is simple: any data member omitted from the initialiser list, shall be
    >>>> value-initialised ([class.base.init]/3), not *un*initialised. UDT or
    >>>> not does not matter. Value-initialisation is performed differently for
    >>>> POD than for non-POD, but that does not change the fact that an omitted
    >>>> member is value-initialised.
    >>>> V
    >>>> --
    >>> I might be reading an old copy of the standard, but the version I'm
    >>> reading (http://www.kuzbass.ru:8086/docs/isocpp) states:
    >>> [.."final draft" of 1998 standard quoted..]

    >> It must be different from the currently active language standard. Get
    >> yourself a copy and check. I vaguely remember that there were some
    >> changes made to initialization clause. Also, look in the archives for
    >> posts from Andrew Koenig on "value-initialization", you will most likely
    >> find that the initialization was reworked/reworded.
    >>
    >> V
    >> --
    >> Please remove capital 'A's when replying by e-mail
    >> I do not respond to top-posted replies, please don't ask

    >
    > I got the active standard, ISO/IEC 14882:2003(E), and still couldn't
    > find anywhere that stated what you mentioned:
    >
    > "then the rule is simple: any data member omitted from the initialiser
    > list, shall be
    > value-initialised ([class.base.init]/3), not *un*initialised. UDT or
    > not does not matter. Value-initialisation is performed differently
    > for
    > POD than for non-POD, but that does not change the fact that an
    > omitted
    > member is value-initialised."
    >
    > class.base.init/3 stated:
    >
    > "— if the expression-list of the mem-initializer is omitted, the base
    > class or member subobject is value initialized (see 8.5);
    > — otherwise, the subobject indicated by mem-initializer-id is direct-
    > initialized using expression-list as the initializer (see 8.5)."
    >
    > This is concerned with not the mem-initializer-id being absent, but
    > rather the expression-list being absent.
    >
    > class.base.init/4 states:
    >
    > "— If the entity is a nonstatic data member of (possibly cv-qualified)
    > class type (or array thereof) or a base
    > class, and the entity class is a non-POD class, the entity is default-
    > initialized (8.5). If the entity is a nonstatic
    > data member of a const-qualified type, the entity class shall have a
    > user-declared default constructor.
    > — Otherwise, the entity is not initialized. If the entity is of const-
    > qualified type or reference type, or of a
    > (possibly cv-qualified) POD class type (or array thereof) containing
    > (directly or indirectly) a member of
    > a const-qualified type, the program is ill-formed."
    >
    > So Foo::x will be unitialized if it is left out in the initialisation
    > list (and not assigned a value in the body of the constructor).
    >
    > My interpretation of default versus value initialisation is that the
    > only difference is that default initialisation calls the default
    > constructor regardless of whether the ctor is user defined or not,
    > whereas value-initialisation only calls the default constructor if it
    > was user defined, otherwise it value-intialises the member.
    >
    > The standard states that:
    >
    > "The object is default-initialized if there is no initializer, or
    > value-initialized if the initializer is ()."
    >
    > So using the example:
    >
    > class Foo
    > {
    > private:
    > int x;
    > public:
    > ~Foo() {};
    >
    > };
    >
    > If we write:
    >
    > Foo x; // default-initialisation
    >
    > Then the (compiler-generated) constructor will be called, which is
    > equivalent to an empty constructor with an empty initializer list, so
    > Foo::x will remain uniitialized.
    >
    > However,
    >
    > Foo x() // value-initialisation
    >
    > Then, as there is no user-defined constructor, the members of x will
    > be value-initialised, which means that Foo::x will be zero
    > initialised!
    >
    > Is this correct?
    >
    > I'm still unsure of what happens if you do not initialise a data
    > member in the copy constructor, but I think the above needs to be
    > sorted first.
    >
    > Taras
    >
    >

    Kind of.
    Foo x(); is a function declaration :)
    Buf Foo x = Foo(); will initialize i to zero and Foo x; won't.

    Why did you need a destructor though -- just wondering?

    The answer to your second question is also yes. If you have a
    user=defined constructor and do not initialize a member, the member will
    stay uninitialized.

    -Pavel
    Pavel, Oct 27, 2009
    #9
  10. Taras_96

    Taras_96 Guest

    So to recap.

    * The compiler generated default constructor is a constructor with an
    empty initializer list and body
    * If a constructor ommits a member from the initialization list:
    ** If the entity is a nonstatic data member of (possibly cv-qualified)
    class type (or array thereof) or a base
    class, and the entity class is a non-POD class, the entity is default-
    initialized (8.5).
    ** Otherwise, the entity is not initialized

    Foo foo; // default initialization
    The default constructor is called (regardless of whether it is user
    defined or not)

    Foo foo = Foo(); // value initialization
    If there IS a user declared constructor, it is called (and program is
    ill formed if there is no default constructor)
    If a non-union class type without a user-declared constructor, then
    every non-static data member and base-class component of T is value-
    initialized;

    So, 'int Foo::x; will not be initialized IF:

    - foo is default initialized and the compiler generated default
    constructor is used
    - foo is default initialized and a user generated default constructor
    is used, *and* Foo::x is ommitted from the initializer list
    - foo is value initialized and a user generated default constructor is
    used, *and* Foo::x is ommitted from the initializer list

    NB: int Foo::x WILL be initialized if foo is value initialized, and
    there is no user declared default constructor (unlike if you were to
    default initialize foo), as "every non-static data member and base-
    class component of T is value-initialized"

    This to me is unusual that the behaviour wasn't made consistent... why
    not just make it so that all members are always initialized,
    regardless of whether the parent object is default initialized, value
    initialized, or if a user declared constructor is used.

    Taras
    Taras_96, Oct 29, 2009
    #10
  11. Taras_96

    Pavel Guest

    Taras_96 wrote:
    > So to recap.
    >
    > * The compiler generated default constructor is a constructor with an
    > empty initializer list and body
    > * If a constructor ommits a member from the initialization list:
    > ** If the entity is a nonstatic data member of (possibly cv-qualified)
    > class type (or array thereof) or a base
    > class, and the entity class is a non-POD class, the entity is default-
    > initialized (8.5).
    > ** Otherwise, the entity is not initialized
    >
    > Foo foo; // default initialization
    > The default constructor is called (regardless of whether it is user
    > defined or not)
    >
    > Foo foo = Foo(); // value initialization
    > If there IS a user declared constructor, it is called (and program is
    > ill formed if there is no default constructor)
    > If a non-union class type without a user-declared constructor, then
    > every non-static data member and base-class component of T is value-
    > initialized;
    >
    > So, 'int Foo::x; will not be initialized IF:
    >
    > - foo is default initialized and the compiler generated default
    > constructor is used
    > - foo is default initialized and a user generated default constructor
    > is used, *and* Foo::x is ommitted from the initializer list
    > - foo is value initialized and a user generated default constructor is
    > used, *and* Foo::x is ommitted from the initializer list
    >
    > NB: int Foo::x WILL be initialized if foo is value initialized, and
    > there is no user declared default constructor (unlike if you were to
    > default initialize foo), as "every non-static data member and base-
    > class component of T is value-initialized"
    >
    > This to me is unusual that the behaviour wasn't made consistent... why
    > not just make it so that all members are always initialized,
    > regardless of whether the parent object is default initialized, value
    > initialized, or if a user declared constructor is used.
    >
    > Taras
    >

    My understanding it is for efficiency. If you do not want to initialize
    a data member or you cannot initialize it in initializer (which
    sometimes happens although not as often as it is used as a justification
    for initializing in the body), you would end up to copying to that
    member more than once.

    As opposed to, for example, Java, C++ does not do static analysis of the
    constructor body so it cannot (is not required to) ensure that the data
    member that is not initialized in initializer is assigned to (or
    initialized by other means) in the body of the constructor. Thus to
    allow the calculation of a data member value in the constructor's body
    without the overhead of extra copy, C++ also has to allow you to leave
    it uninitialized. C++'s cheese (passing function parameters by
    references and pointers) is not free -- it stays in the way of complete
    static analysis by the compiler.

    Certainly there are also situations where you do not want to initialize
    at all, either in the initializer or in the body. Imagine you have a
    cache of a significant but fixed size, some char cache[MAX_SIZE]. In
    order to avoid an extra dynamic memory (de)allocation, you make it a
    bare C array. You may have a single boolean "bool cacheDirty"
    (initialized to true) or used size "size_t cacheSize;" (initialized to
    zero) and avoid unnecessary copying into the whole cache on the creation
    of the class.

    -Pavel
    Pavel, Oct 31, 2009
    #11
    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. Samuele Armondi
    Replies:
    4
    Views:
    1,018
    Victor Bazarov
    Jun 25, 2003
  2. Jason Heyes
    Replies:
    6
    Views:
    368
    Norbert Riedlin
    Dec 4, 2003
  3. Tim
    Replies:
    2
    Views:
    1,497
  4. Ook
    Replies:
    10
    Views:
    546
  5. Tim Clacy
    Replies:
    8
    Views:
    385
    Tim Clacy
    May 30, 2006
Loading...

Share This Page