Default constructor weirdness in member initialization list

Discussion in 'C++' started by mhvaughn@gmail.com, Feb 1, 2008.

  1. Guest

    struct S1
    {
    int i;
    };

    struct S2 {
    S1 s;
    // version 1
    S2() {} ;
    // version 2
    S2() : s() {} ;
    };

    int main()
    {
    S2 s;
    printf( "%d\n", s.s.i );
    return 0;
    }

    ----------

    With version 1 of the S2 constructor the program will spew random
    values as expected.
    With version 2 of the S2 constructor the program only spews zeros.
    Does explicitly calling the default constructor in the member
    initialization list somehow cause the "default" constructor for the
    int in S1 to be called?
    , Feb 1, 2008
    #1
    1. Advertising

  2. * :
    > struct S1
    > {
    > int i;
    > };
    >
    > struct S2 {
    > S1 s;
    > // version 1
    > S2() {} ;
    > // version 2
    > S2() : s() {} ;
    > };
    >
    > int main()
    > {
    > S2 s;
    > printf( "%d\n", s.s.i );
    > return 0;
    > }
    >
    > ----------
    >
    > With version 1 of the S2 constructor the program will spew random
    > values as expected.
    > With version 2 of the S2 constructor the program only spews zeros.
    > Does explicitly calling the default constructor in the member
    > initialization list somehow cause the "default" constructor for the
    > int in S1 to be called?


    No, an int does not have a constructor: the initialization syntax just
    resembles an explicit constructor call.

    Since you initialize the member it is initialized.

    In standard C++ this initialization syntax also works for an array
    member, although compiler support for that varies.

    Cheers, & hth

    - Alf


    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Feb 1, 2008
    #2
    1. Advertising

  3. devp Guest

    On Feb 1, 5:18 am, wrote:
    > struct S1
    > {
    > int i;
    >
    > };
    >
    > struct S2 {
    > S1 s;
    > // version 1
    > S2() {} ;
    > // version 2
    > S2() : s() {} ;
    >
    > };
    >
    > int main()
    > {
    > S2 s;
    > printf( "%d\n", s.s.i );
    > return 0;
    >
    > }
    >
    > ----------
    >
    > With version 1 of the S2 constructor the program will spew random
    > values as expected.
    > With version 2 of the S2 constructor the program only spews zeros.
    > Does explicitly calling the default constructor in the member
    > initialization list somehow cause the "default" constructor for the
    > int in S1 to be called?


    Hi
    I tried the program with g++ it works same both ways, as should. Which
    compiler did you use?

    cheers
    projyal
    devp, Feb 1, 2008
    #3
  4. * devp:
    > On Feb 1, 5:18 am, wrote:
    >> struct S1
    >> {
    >> int i;
    >>
    >> };
    >>
    >> struct S2 {
    >> S1 s;
    >> // version 1
    >> S2() {} ;
    >> // version 2
    >> S2() : s() {} ;
    >>
    >> };
    >>
    >> int main()
    >> {
    >> S2 s;
    >> printf( "%d\n", s.s.i );
    >> return 0;
    >>
    >> }
    >>
    >> ----------
    >>
    >> With version 1 of the S2 constructor the program will spew random
    >> values as expected.
    >> With version 2 of the S2 constructor the program only spews zeros.
    >> Does explicitly calling the default constructor in the member
    >> initialization list somehow cause the "default" constructor for the
    >> int in S1 to be called?

    >
    > Hi
    > I tried the program with g++ it works same both ways, as should.


    Version 1 has undefined behavior.

    Undefined behavior includes doing what one incorrectly might expect.


    > Which compiler did you use?


    Different compilers, versions of the same compiler, and invocations of
    the same version of the same compiler but with different options, often
    yield different results for undefined behavior.

    Cheers, & hth.,

    - Alf

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Feb 1, 2008
    #4
  5. Guest

    On Jan 31, 5:17 pm, "Alf P. Steinbach" <> wrote:
    > * :
    >
    >
    >
    > > struct S1
    > > {
    > > int i;
    > > };

    >
    > > struct S2 {
    > > S1 s;
    > > // version 1
    > > S2() {} ;
    > > // version 2
    > > S2() : s() {} ;
    > > };

    >
    > > int main()
    > > {
    > > S2 s;
    > > printf( "%d\n", s.s.i );
    > > return 0;
    > > }

    >
    > > ----------

    >
    > > With version 1 of the S2 constructor the program will spew random
    > > values as expected.
    > > With version 2 of the S2 constructor the program only spews zeros.
    > > Does explicitly calling the default constructor in the member
    > > initialization list somehow cause the "default" constructor for the
    > > int in S1 to be called?

    >
    > No, an int does not have a constructor: the initialization syntax just
    > resembles an explicit constructor call.
    >
    > Since you initialize the member it is initialized.
    >


    But the member I initialized is of type S1. Since there is no
    constructor provided for S1 the compiler should provide one which
    should do nothing. I'm perfectly willing to accept that it just seems
    like its doing something, I guess I just wanted to double-check that
    default constructors in member initialization lists are not special in
    some way (e.g., like global structs whose members are zeroed out when
    created).

    > In standard C++ this initialization syntax also works for an array
    > member, although compiler support for that varies.
    >
    > Cheers, & hth
    >
    > - Alf
    >
    > --
    > A: Because it messes up the order in which people normally read text.
    > Q: Why is it such a bad thing?
    > A: Top-posting.
    > Q: What is the most annoying thing on usenet and in e-mail?
    , Feb 1, 2008
    #5
  6. Guest

    On Jan 31, 5:22 pm, devp <> wrote:
    > On Feb 1, 5:18 am, wrote:
    >
    >
    >
    > > struct S1
    > > {
    > > int i;

    >
    > > };

    >
    > > struct S2 {
    > > S1 s;
    > > // version 1
    > > S2() {} ;
    > > // version 2
    > > S2() : s() {} ;

    >
    > > };

    >
    > > int main()
    > > {
    > > S2 s;
    > > printf( "%d\n", s.s.i );
    > > return 0;

    >
    > > }

    >
    > > ----------

    >
    > > With version 1 of the S2 constructor the program will spew random
    > > values as expected.
    > > With version 2 of the S2 constructor the program only spews zeros.
    > > Does explicitly calling the default constructor in the member
    > > initialization list somehow cause the "default" constructor for the
    > > int in S1 to be called?

    >
    > Hi
    > I tried the program with g++ it works same both ways, as should. Which
    > compiler did you use?


    [615]$g++ -v
    Using built-in specs.
    Target: x86_64-linux-gnu
    Configured with: ../src/configure -v --enable-languages=c,c+
    +,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-
    system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-
    threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/
    4.1.3 --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu
    --enable-libstdcxx-debug --enable-mpfr --enable-checking=release
    x86_64-linux-gnu
    Thread model: posix
    gcc version 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)


    >
    > cheers
    > projyal
    , Feb 1, 2008
    #6
  7. * :
    > On Jan 31, 5:17 pm, "Alf P. Steinbach" <> wrote:
    >> * :
    >>
    >>> struct S1
    >>> {
    >>> int i;
    >>> };
    >>> struct S2 {
    >>> S1 s;
    >>> // version 1
    >>> S2() {} ;
    >>> // version 2
    >>> S2() : s() {} ;
    >>> };
    >>> int main()
    >>> {
    >>> S2 s;
    >>> printf( "%d\n", s.s.i );
    >>> return 0;
    >>> }
    >>> ----------
    >>> With version 1 of the S2 constructor the program will spew random
    >>> values as expected.
    >>> With version 2 of the S2 constructor the program only spews zeros.
    >>> Does explicitly calling the default constructor in the member
    >>> initialization list somehow cause the "default" constructor for the
    >>> int in S1 to be called?

    >> No, an int does not have a constructor: the initialization syntax just
    >> resembles an explicit constructor call.
    >>
    >> Since you initialize the member it is initialized.
    >>

    >
    > But the member I initialized is of type S1.


    Previous comment still applies, but to be honest, I didn't notice...


    > Since there is no
    > constructor provided for S1 the compiler should provide one which
    > should do nothing.


    If it's used (ref. §12.1/7).

    But, the language being as backwards in certain respects as it is, to
    use that do-nothing automatic default constructor you have to /not/
    indicate that you want it, e.g. for a local variable,

    S1 o; // Do-nothing auto default constructor used, §12.1/8.

    If you try to add parentheses to say you want to use the darned thing,
    then in the C++ "do the opposite of what's expected"-way it isn't used:

    o = S1(); // Not an invocation of the do-nothing def. constructor.

    What happens here is according to C++98 a zero-initialization (§8.5/7,
    §8.5/5) and IIRC according to C++03 a value-initialization, essentially
    zeroing or default-initializing members depending on whether they have
    user-defined default constructors or not. And the same applies to your
    code above, in the second version. So the int is zeroed, and that
    zeroing does not involve a constructor, not even of S1.


    > I'm perfectly willing to accept that it just seems
    > like its doing something, I guess I just wanted to double-check that
    > default constructors in member initialization lists are not special in
    > some way (e.g., like global structs whose members are zeroed out when
    > created).


    You're not using the S1 default constructor; see above.


    Cheers, & hth.,

    - Alf

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Feb 1, 2008
    #7
  8. wrote:
    > struct S1
    > {
    > int i;
    > };
    >
    > struct S2 {
    > S1 s;
    > // version 1
    > S2() {} ;
    > // version 2
    > S2() : s() {} ;
    > };
    >
    > int main()
    > {
    > S2 s;
    > printf( "%d\n", s.s.i );
    > return 0;
    > }
    >
    > ----------
    >
    > With version 1 of the S2 constructor the program will spew random
    > values as expected.


    OK.

    > With version 2 of the S2 constructor the program only spews zeros.


    Yes.

    > Does explicitly calling the default constructor in the member
    > initialization list somehow cause the "default" constructor for the
    > int in S1 to be called?


    Firstly, you are not "explicitly calling" the default constructor of S1
    by using 's()' syntax in the constructor initializer list. In C++
    there's no syntax and way in general to "explicitly call" a constructor.

    Secondly, only obects of class types can have constructors in C++.
    Objects of type 'int' (as 'S1::i' in your case) have no construtors
    whatsoever.

    Now, when you specify a '()' initializer for an object, it causes so
    called "value-initialization" of that object. Note, that the notion of
    "initialization" in C++ is more general that the notion of
    "construction". Initialization does not necessarily involve construction
    (and constructors). For an object of class type without any user-defined
    constructors (like 's' of type 'S1' in your example),
    value-initialization does not involve any constructors of S1.
    Value-initialization for an object of type S1 results in
    value-initialization of all of its subobjects. In this case it is
    value-initialization if 'S1::i' member of type 'int'. For type 'int'
    value-initialization means zero-initialization. I.e. 'S1::i' is set to
    zero. It is done directly, without involving any constructors.

    Note once again, that the only constructor that is involved in this
    process is the constructor of 'S2'. There are no more constructors
    involved here. 'S1' and its member 'S1::i' are initialized directly.

    --
    Best regards,
    Andrey Tarasevich
    Andrey Tarasevich, Feb 1, 2008
    #8
  9. * Andrey Tarasevich:
    > wrote:
    >> struct S1
    >> {
    >> int i;
    >> };
    >>
    >> struct S2 {
    >> S1 s;
    >> // version 1
    >> S2() {} ;
    >> // version 2
    >> S2() : s() {} ;
    >> };
    >>
    >> int main()
    >> {
    >> S2 s;
    >> printf( "%d\n", s.s.i );
    >> return 0;
    >> }
    >>
    >> ----------
    >>
    >> With version 1 of the S2 constructor the program will spew random
    >> values as expected.

    >
    > OK.
    >
    >> With version 2 of the S2 constructor the program only spews zeros.

    >
    > Yes.
    >
    >> Does explicitly calling the default constructor in the member
    >> initialization list somehow cause the "default" constructor for the
    >> int in S1 to be called?

    >
    > Firstly, you are not "explicitly calling" the default constructor of S1
    > by using 's()' syntax in the constructor initializer list.


    Right.


    > In C++
    > there's no syntax and way in general to "explicitly call" a constructor.


    I'm sorry, that's incorrect.

    There's no dedicated C++ syntax for constructor calls. What the syntax
    means depends on context. Whether to say that an explicit constructor
    call is an explicit constructor call is a terminologial issue.

    The language's creator calls an explicit constructor call an explicit
    constructor call. Some programmers who post in this newsgroup have
    taken issue with that, insisting that the word "call" is inappropriate
    for source code level constructor calls, thus rendering e.g. the
    standard's definition of default constructor (what we're discussing
    here) meaningless. But to each his own, just don't propagate the myth
    that that terminological stance has any substance. :)


    Cheers, & hth.,

    - Alf


    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Feb 1, 2008
    #9
  10. Alf P. Steinbach wrote:
    > ...
    >> In C++ there's no syntax and way in general to "explicitly call" a
    >> constructor.

    >
    > I'm sorry, that's incorrect.
    >
    > There's no dedicated C++ syntax for constructor calls. What the syntax
    > means depends on context. Whether to say that an explicit constructor
    > call is an explicit constructor call is a terminologial issue.


    I disagree. Constructors are functions. They are special functions, but
    functions nevertheless. For this reason I'd expect the "explicit
    constructor call", if it existed, to be have the function call
    semantics. However, if I'm not mistaken, there's no way to call
    constructor in C++ by using function call semantics. Constructors calls
    in C++ are "side effects" of the more generic process called
    "initialization". It is is invoked by various language constructs
    having... well, initialization semantics, which is essentially different
    from function call semantics. This is why I say that there's no way to
    "call" a constructor in C++.

    > The language's creator calls an explicit constructor call an explicit
    > constructor call.


    Where? In TC++PL? If yes, then sorry, but that book is not canonical in
    the context of ANSI standard C++ discussion. It is intentionally
    simplified to be more accessible for newcomers. And the price of that
    simplification is that sometimes it makes statements, which are simply
    incorrect from the standard C++ point of view. (For example, it states
    that scalar types have constructors, if I remember correctly).

    --
    Best regards,
    Andrey Tarasevich
    Andrey Tarasevich, Feb 1, 2008
    #10
  11. * Andrey Tarasevich:
    > Alf P. Steinbach wrote:
    >> ...
    >>> In C++ there's no syntax and way in general to "explicitly call" a
    >>> constructor.

    >>
    >> I'm sorry, that's incorrect.
    >>
    >> There's no dedicated C++ syntax for constructor calls. What the
    >> syntax means depends on context. Whether to say that an explicit
    >> constructor call is an explicit constructor call is a terminologial
    >> issue.

    >
    > I disagree. Constructors are functions. They are special functions, but
    > functions nevertheless. For this reason I'd expect the "explicit
    > constructor call", if it existed, to be have the function call
    > semantics.


    Notwithstanding the impracticality of adopting a terminology that
    excludes comprehension of crucial parts of the standard, the above is a
    circular argument, defining "call" as any function call that is not a
    source level constructor call, then maintaining that that in some sense
    means that "call" is unsuitable for source level constructor calls.

    If you try to define what you think you mean non-circularly you run into
    problems with e.g. explicit destructor calls (semantics) and implicit
    type conversion operator calls (syntax).

    This is the same kind of problem that people run into when they try to
    define religious beliefs. A Canadian pilot who tried to communicate
    with God -- in-flight -- was placed in irons last week, and sent to
    hospital when the plane landed, whereas to become pilot of the United
    States of America you have to insist on believing in that kind of thing
    and demonstrate that you practice... The only way out while maintaining
    such belief is to steadfastly ignore reality, to double-think.


    >
    > Where? In TC++PL?


    E.g.

    Andrew Koenig & Bjarne Stroustrup:
    "Foundations for Native C++ Styles"
    <url:
    http://parasol.tamu.edu/people/rwerger/Courses/434/c++primer.ps>.

    "The explicit constructor call greater<int>() will serve the same
    purpose by creating an anonymous object:"

    Might throw in Nicola Josuttis too if you want more. :)


    > If yes, then sorry, but that book is not canonical in
    > the context of ANSI standard C++ discussion. It is intentionally
    > simplified to be more accessible for newcomers. And the price of that
    > simplification is that sometimes it makes statements, which are simply
    > incorrect from the standard C++ point of view. (For example, it states
    > that scalar types have constructors, if I remember correctly).


    See above.


    Cheers, & hth.,

    - Alf

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Feb 1, 2008
    #11
  12. James Kanze Guest

    On Feb 1, 9:17 pm, Andrey Tarasevich <>
    wrote:
    > Alf P. Steinbach wrote:
    > > ...
    > >> In C++ there's no syntax and way in general to "explicitly call" a
    > >> constructor.


    > > I'm sorry, that's incorrect.


    > > There's no dedicated C++ syntax for constructor calls. What
    > > the syntax means depends on context. Whether to say that an
    > > explicit constructor call is an explicit constructor call is
    > > a terminologial issue.


    > I disagree. Constructors are functions. They are special
    > functions, but functions nevertheless. For this reason I'd
    > expect the "explicit constructor call", if it existed, to be
    > have the function call semantics. However, if I'm not
    > mistaken, there's no way to call constructor in C++ by using
    > function call semantics. Constructors calls in C++ are "side
    > effects" of the more generic process called "initialization".


    More importantly, every way you can "call" a constructor
    involves memory allocation.

    > It is is invoked by various language constructs having...
    > well, initialization semantics, which is essentially different
    > from function call semantics. This is why I say that there's
    > no way to "call" a constructor in C++.


    It depends on the level. One of the syntax's for the explicit
    creation of a temporary object "looks" like a function call,
    with the name of the function being that of the class (which is
    the name you use to declare a constructor). So traditionally, a
    lot of people have informally called it an explicit constructor
    call. The standard calls it an "explicit type conversion
    (functional notation)", which is 100% accurate when there is
    only one argument, but doesn't really make sense otherwise. And
    of course, there are lots of ways to "call" a constructor---the
    only question is whether any of them merit the name "explicit".

    > > The language's creator calls an explicit constructor call an
    > > explicit constructor call.


    > Where? In TC++PL? If yes, then sorry, but that book is not
    > canonical in the context of ANSI standard C++ discussion. It
    > is intentionally simplified to be more accessible for
    > newcomers. And the price of that simplification is that
    > sometimes it makes statements, which are simply incorrect from
    > the standard C++ point of view. (For example, it states that
    > scalar types have constructors, if I remember correctly).


    I think that there are even one or two places in the standard
    where the expression "explicit constructor call" occurs.
    Regretfully, the standard doesn't define what it means by that,
    so we're still left guessing. I don't like the term "explicit
    constructor call" because for most people I know, it immediately
    calls to mind the "explicit type conversion (functional
    notation)" of the standard, and that, of course, doesn't
    necessarily result in a constructor call at all. I don't like
    the term used in the standard for this either, since I find it
    hard to call something like "MyClass()" or "MyClass(a, b)" a
    type conversion---what type is being converted. So I resort to
    "explicit creation of a temporary". Similarly, I'll find other
    expressions for the other cases where I end up calling a
    constructor: a placement new expression, for example (which is
    semantically the closest you can come to really "calling the
    constructor", but syntactically, of course, is a new
    expression).

    --
    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, Feb 1, 2008
    #12
  13. Guest

    On Feb 1, 10:30 am, "Alf P. Steinbach" <> wrote:
    > * :
    >
    >
    >
    > > On Jan 31, 5:17 pm, "Alf P. Steinbach" <> wrote:
    > >> * :

    >
    > >>> struct S1
    > >>> {
    > >>> int i;
    > >>> };
    > >>> struct S2 {
    > >>> S1 s;
    > >>> // version 1
    > >>> S2() {} ;
    > >>> // version 2
    > >>> S2() : s() {} ;
    > >>> };
    > >>> int main()
    > >>> {
    > >>> S2 s;
    > >>> printf( "%d\n", s.s.i );
    > >>> return 0;
    > >>> }
    > >>> ----------
    > >>> With version 1 of the S2 constructor the program will spew random
    > >>> values as expected.
    > >>> With version 2 of the S2 constructor the program only spews zeros.
    > >>> Does explicitly calling the default constructor in themember
    > >>>initializationlist somehow cause the "default" constructor for the
    > >>> int in S1 to be called?
    > >> No, an int does not have a constructor: theinitializationsyntax just
    > >> resembles an explicit constructor call.

    >
    > >> Since you initialize thememberit is initialized.

    >
    > > But thememberI initialized is of type S1.

    >
    > Previous comment still applies, but to be honest, I didn't notice...
    >
    > > Since there is no
    > > constructor provided for S1 the compiler should provide one which
    > > should do nothing.

    >
    > If it's used (ref. §12.1/7).
    >
    > But, the language being as backwards in certain respects as it is, to
    > use that do-nothing automatic default constructor you have to /not/
    > indicate that you want it, e.g. for a local variable,
    >
    > S1 o; // Do-nothing auto default constructor used, §12.1/8.
    >
    > If you try to add parentheses to say you want to use the darned thing,
    > then in the C++ "do the opposite of what's expected"-way it isn't used:
    >
    > o = S1(); // Not an invocation of the do-nothing def. constructor.
    >
    > What happens here is according to C++98 a zero-initialization(§8.5/7,
    > §8.5/5) and IIRC according to C++03 a value-initialization, essentially
    > zeroing or default-initializing members depending on whether they have
    > user-defined default constructors or not. And the same applies to your
    > code above, in the second version. So the int is zeroed, and that
    > zeroing does not involve a constructor, not even of S1.
    >
    > > I'm perfectly willing to accept that it just seems
    > > like its doing something, I guess I just wanted to double-check that
    > > default constructors inmemberinitializationlists are not special in
    > > some way (e.g., like global structs whose members are zeroed out when
    > > created).

    >
    > You're not using the S1 default constructor; see above.
    >
    > Cheers, & hth.,
    >
    > - Alf
    >
    > --
    > A: Because it messes up the order in which people normally read text.
    > Q: Why is it such a bad thing?
    > A: Top-posting.
    > Q: What is the most annoying thing on usenet and in e-mail?


    First off, thanks very much for the explanation... that behavior is
    unintuitive (to me) but good to know about.

    I've been playing around with bits of code related to implicit
    creation of default constructors and so far I've been able to relate
    code behavior to the description in the standard except for the
    following:

    #include <stdio.h>

    // struct S1 { int j; };
    struct S1 { int j; S1 () {}; };
    struct S2 { int i; S1 s1; };

    int main()
    {
    S2 s2 = S2();
    printf( "%d,%d\n", s2.i, s2.s1.j );
    return 0;
    }

    There is no user-defined default constructor for S2 so an implicit
    constructor is automatically declared by the compiler.
    The first line of main creates an object with an initializer so the
    compiler doesn't define that default constructor.
    So the s2 struct is default-initialized but (since it has no defined
    constructor) is zero-initialized.
    Why, then, is s2.i undefined?
    Also, is there some part of the standard which clearly indicates when
    the constructor for S1 gets called?
    , Feb 4, 2008
    #13
  14. * :
    >>

    [snip quoted signature, please don't quote signatures]

    > I've been playing around with bits of code related to implicit
    > creation of default constructors and so far I've been able to relate
    > code behavior to the description in the standard except for the
    > following:
    >
    > #include <stdio.h>
    >
    > // struct S1 { int j; };
    > struct S1 { int j; S1 () {}; };
    > struct S2 { int i; S1 s1; };
    >
    > int main()
    > {
    > S2 s2 = S2();
    > printf( "%d,%d\n", s2.i, s2.s1.j );
    > return 0;
    > }
    >
    > There is no user-defined default constructor for S2 so an implicit
    > constructor is automatically declared by the compiler.
    > The first line of main creates an object with an initializer so the
    > compiler doesn't define that default constructor.
    > So the s2 struct is default-initialized but (since it has no defined
    > constructor) is zero-initialized.


    The rules here are slightly different in C++98 (the original standard)
    and C++03 (first technical corrigendum, the TC1).

    C++03 introduced the notion of "value initialization" in order to tackle
    just this problem, a correction of the C++98 semantics.

    With C++98 semantics what happens is, as you state, a
    default-initialization. And the problem with that is that the
    definition of default-initialization, in §8.5./5, starts with "if T is a
    non-POD class type, the default constructor for T is called". And in
    the example above S2 is non-POD[1] (not a plain old C-like data type)
    because it contains a member of a type with a defined constructor, which
    is not something possible in C, and so according to C++98 semantics you
    just get a call of your do-nothing auto-created default constructor.

    With C++03 semantics what happens is a value initialization, intended to
    correct this problem. The wording of value initialization starts with
    "if T is a class type with a user-declared constructor, then the default
    constructor for T is called". This doesn't apply to S2, which doesn't
    have a user-declared constructor. But the next alternative, "if T is 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", applies, recursively for S2::i and S2::s1. And for
    S2::i the last alternative of this list applies, zero-initializion, and
    for S2::s1 the first alternative applies, default constructor called.

    So essentialy the compiler or compilers you have tested with evidently
    implemented C++98 semantics, or perhaps just incorrect initialization,
    not C++03 semantics. One remedy is to upgrade the compiler(s). Another
    more general solution is to simply define a default constructor.

    Cheers, & hth.,

    - Alf


    Notes:
    [1] Technically it is an "aggregate" type.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Feb 4, 2008
    #14
  15. Guest

    On Feb 4, 3:05 pm, "Alf P. Steinbach" <> wrote:
    > * :
    >
    > [snip quoted signature, please don't quote signatures]
    >
    > > I've been playing around with bits of code related to implicit

    >
    >
    >
    > > creation of default constructors and so far I've been able to relate
    > > code behavior to the description in the standard except for the
    > > following:

    >
    > > #include <stdio.h>

    >
    > > // struct S1 { int j; };
    > > struct S1 { int j; S1 () {}; };
    > > struct S2 { int i; S1 s1; };

    >
    > > int main()
    > > {
    > > S2 s2 = S2();
    > > printf( "%d,%d\n", s2.i, s2.s1.j );
    > > return 0;
    > > }

    >
    > > There is no user-defined default constructor for S2 so an implicit
    > > constructor is automatically declared by the compiler.
    > > The first line of main creates an object with an initializer so the
    > > compiler doesn't define that default constructor.
    > > So the s2 struct is default-initialized but (since it has no defined
    > > constructor) is zero-initialized.

    >
    > The rules here are slightly different in C++98 (the original standard)
    > and C++03 (first technical corrigendum, the TC1).
    >
    > C++03 introduced the notion of "valueinitialization" in order to tackle
    > just this problem, a correction of the C++98 semantics.
    >
    > With C++98 semantics what happens is, as you state, a
    > default-initialization. And the problem with that is that the
    > definition of default-initialization, in §8.5./5, starts with "if T is a
    > non-POD class type, the default constructor for T is called". And in
    > the example above S2 is non-POD[1] (not a plain old C-like data type)
    > because it contains amemberof a type with a defined constructor, which
    > is not something possible in C, and so according to C++98 semantics you
    > just get a call of your do-nothing auto-created default constructor.
    >
    > With C++03 semantics what happens is a valueinitialization, intended to
    > correct this problem. The wording of valueinitializationstarts with
    > "if T is a class type with a user-declared constructor, then the default
    > constructor for T is called". This doesn't apply to S2, which doesn't
    > have a user-declared constructor. But the next alternative, "if T is a
    > non-union class type without a user-declared constructor, then every
    > non-static datamemberand base-class component of T is
    > value-initialized", applies, recursively for S2::i and S2::s1. And for
    > S2::i the last alternative of this list applies, zero-initializion, and
    > for S2::s1 the first alternative applies, default constructor called.
    >
    > So essentialy the compiler or compilers you have tested with evidently
    > implemented C++98 semantics, or perhaps just incorrectinitialization,
    > not C++03 semantics. One remedy is to upgrade the compiler(s). Another
    > more general solution is to simply define a default constructor.
    >
    > Cheers, & hth.,
    >
    > - Alf
    >
    > Notes:
    > [1] Technically it is an "aggregate" type.
    >
    > --
    > A: Because it messes up the order in which people normally read text.
    > Q: Why is it such a bad thing?
    > A: Top-posting.
    > Q: What is the most annoying thing on usenet and in e-mail?


    Thanks very much. I think it's all clear now... turns out I was
    confused on the definition of POD/nonPOD.
    , Feb 5, 2008
    #15
    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. steve
    Replies:
    4
    Views:
    523
    Brian van den Broek
    Mar 13, 2005
  2. Replies:
    3
    Views:
    844
    Peter_Julian
    Oct 10, 2005
  3. Generic Usenet Account
    Replies:
    10
    Views:
    2,218
  4. aaragon
    Replies:
    2
    Views:
    614
    James Kanze
    Nov 2, 2008
  5. balaji
    Replies:
    3
    Views:
    939
    Jens Thoms Toerring
    Aug 10, 2011
Loading...

Share This Page