questions about object initialization, default-init and value-init

Discussion in 'C++' started by Jess, May 2, 2007.

  1. Jess

    Jess Guest

    Hello,

    I tried several books to find out the details of object
    initialization. Unfortunately, I'm still confused by two specific
    concepts, namely default-initialization and value-initialization. I
    think default-init calls default constructor for class objects and
    sets garbage values to PODs. Value-init also calls default
    constructor for class objects and sets 0s to POD types. This is what
    I've learned from the books (especially Accelerated C++). However, I
    don't think my understanding about these concepts is adequate and I'm
    not sure under what situations each of these two init methods is
    used. Therefore, I'm posting my questions below along with what I
    understand about these two init methods. I'd appreciate it if someone
    could answer my questions and point out my mistakes. Thanks.

    1. Default initialization is used when we create an object using the
    form "T t", where T can be a POD type or class type. If this happens,
    the following occurs:
    a. if T is POD, then "t" is garbage value

    b. if T is class, then it's default constructor is invoked. If
    there's no default contructor, the compiler will synthesize one.
    (i). If there's a default constructor, then all T's POD member data is
    initialized according to the constructor initializer list; any POD
    member not mentioned in the initializer list gets default-init, with
    garbage value. If T has a class-typed member (say of type A), then
    A's default constructor is called and if A has no default constructor,
    then the synthesized constructor will be called. FInally, the
    constructor's body is entered.
    (ii). If there is no default constructor, then the synthesized
    constructor will be called. All POD member gets garbage data and
    class members have their default constructor (or synthesized default
    constructors) invoked.

    Is this what happens to default-init? Moreover, to init POD member in
    the constructor initializer, I can do things like "x(10)" and also
    "x()" where "x" is an int, is this right? If "x()" is used, then "x"
    gets value-init to 0?

    2. Value-initialization happens if a constructor is explicitly invoked
    like "T t(arg)", its copy constructor is invoked. For a class type
    object:
    a. if it's created by invoking a constructor like "T t(arg)", then all
    its POD member gets initialized according to the constructor
    initializer; any POD member not mentioned gets value-init to 0. But
    what happens to those class-typed members? Are their default
    constructors (or synthesized one) called? I think after all these are
    done, the constructor's body is entered.

    b. if the T object is created through copy constructor, then the
    values of the existing objects are copied into the new object.
    However, what if we have an example like "B b = B()"? what's the value
    of the tmp object created by "B()"? Is it the result of default-init
    or value-init?

    3. To value-init a POD object, I think the only way is to do something
    like:

    int n = int();
    is this right?

    4. The book Accelerated C++ also says that if an object is used to
    init a container element, either as a side effect of adding new
    element to a "map", or as the elements of a container defined to have
    a given size, then the members will be value-initialized. I checked
    it through an example,

    struct A{
    int x;

    };

    int main(){
    A a[10];
    return 0;

    };

    Then I found out each element in a has it's "x" value as 0. I think
    this is what the author of the book meant. Then I tried another
    example:

    int main(){
    int b[10];
    return 0;

    }

    This time, each element in b has garbage value. Isn't each member of
    b supposed to be value-init to 0?

    Thanks a lot
    Jess
     
    Jess, May 2, 2007
    #1
    1. Advertising

  2. Jess

    James Kanze Guest

    On May 2, 2:08 am, Jess <> wrote:

    > I tried several books to find out the details of object
    > initialization. Unfortunately, I'm still confused by two specific
    > concepts, namely default-initialization and value-initialization.


    Don't feel bad. The definitions for these two have changes
    several times. The simplest solution for the everyday use is to
    consider them synonyms, and not worry about the subtle
    differences. If you design your classes correctly, they
    shouldn't really be relevant anyway.

    > I think default-init calls default constructor for class
    > objects and sets garbage values to PODs.


    No. At least, not as it is defined in the standard.

    > Value-init also calls default
    > constructor for class objects and sets 0s to POD types. This is what
    > I've learned from the books (especially Accelerated C++).


    I think that Andy wrote the book before the term
    value-initialization was added to the standard; he probably was
    defining some terms of his own, just to try to avoid confusion.
    Roughly speaking:

    -- If an object has a user defined constructor---any user
    defined constructor, it is impossible to create an instance
    of the object without calling a constructor. Period.
    Whether the object is a sub-object, or stands alone. You
    don't have to worry about different types of initialization
    in this case, since they're all the same.

    -- For everything but POD types, you should ensure that the
    object has a constructor which initializes everything. Once
    you have to provide a constructor, there's no point in doing
    a half way job. So again, you don't have to worry about the
    different types of initialization.

    -- For PODs, there are three cases:

    . objects with static lifetime, and objects initialized by
    an empty (), are zero initialized,

    . objects with a explicit initializer are always
    completely initialized---fields with missing initializer
    values will be zero initialized, and

    . everything else is uninitialized, random garbage.

    The different types of initialization only become relevant when
    you have constructors which only do a half-way job.

    > However, I don't think my understanding about these concepts
    > is adequate and I'm not sure under what situations each of
    > these two init methods is used. Therefore, I'm posting my
    > questions below along with what I understand about these two
    > init methods. I'd appreciate it if someone could answer my
    > questions and point out my mistakes. Thanks.


    > 1. Default initialization is used when we create an object using the
    > form "T t", where T can be a POD type or class type.


    No. According to the standard (ISO 14882:1998), default
    initialization is used in this case if the object is of non-POD
    class type, otherwise, no initialization is done.

    > If this happens, the following occurs:
    > a. if T is POD, then "t" is garbage value


    > b. if T is class, then it's default constructor is invoked. If
    > there's no default contructor, the compiler will synthesize one.
    > (i). If there's a default constructor, then all T's POD member data is
    > initialized according to the constructor initializer list; any POD
    > member not mentioned in the initializer list gets default-init, with
    > garbage value. If T has a class-typed member (say of type A), then
    > A's default constructor is called and if A has no default constructor,
    > then the synthesized constructor will be called. FInally, the
    > constructor's body is entered.


    > (ii). If there is no default constructor, then the synthesized
    > constructor will be called. All POD member gets garbage data and
    > class members have their default constructor (or synthesized default
    > constructors) invoked.


    That's corresponds pretty well to the effect. With one
    exception: if there is any user defined constructor, the
    compiler will not synthesize a default constructor. If there is
    one or more user defined constructors, but no user defined
    default constructor, you cannot create an instance of the class
    without specifying some arguments for initialization.

    > Is this what happens to default-init?


    It's what happens "by default", when initializing an object with
    no explicit initialization list, provided the object doesn't
    have static storage duration.

    > Moreover, to init POD member in
    > the constructor initializer, I can do things like "x(10)" and also
    > "x()" where "x" is an int, is this right? If "x()" is used, then "x"
    > gets value-init to 0?


    Roughly speaking, X() initializes the object with the value it
    would have as an object with static storage duration; i.e. as if
    it were zero initialized, and then any non-trivial constructor
    were called on it.

    > 2. Value-initialization happens if a constructor is explicitly invoked
    > like "T t(arg)", its copy constructor is invoked. For a class type
    > object:


    Not in the standard. That's explicit initialization. It can
    only be used for a class type, and overload resolution is used
    on the argument list to decide which constructor to call.

    > a. if it's created by invoking a constructor like "T t(arg)", then all
    > its POD member gets initialized according to the constructor
    > initializer; any POD member not mentioned gets value-init to 0.


    No. If the object has static storage duration, it will be
    initially zero initialized, and then the constructor will be
    called, otherwise, the constructor will be called directly.

    If the object doesn't have class type, then this is the
    equivalent of:
    T t = arg ;

    > But
    > what happens to those class-typed members? Are their default
    > constructors (or synthesized one) called? I think after all these are
    > done, the constructor's body is entered.


    All constructors systematically call the constructors of all
    sub-objects, if those sub-objects have a non-trivial
    constructor.

    > b. if the T object is created through copy constructor, then the
    > values of the existing objects are copied into the new object.
    > However, what if we have an example like "B b = B()"? what's the value
    > of the tmp object created by "B()"? Is it the result of default-init
    > or value-init?


    Yes:). According to ISO 14882::1998, it is default-init;
    according to the latest draft, it is value-init, but if you are
    writing reasonable code, it doesn't matter.

    > 3. To value-init a POD object, I think the only way is to do something
    > like:


    > int n = int();
    > is this right?


    value-initialization and default-initialization are the same
    thing for POD objects.

    > 4. The book Accelerated C++ also says that if an object is used to
    > init a container element, either as a side effect of adding new
    > element to a "map", or as the elements of a container defined to have
    > a given size, then the members will be value-initialized. I checked
    > it through an example,


    > struct A{
    > int x;
    > };


    > int main(){
    > A a[10];


    Attention: this is NOT a container, at least not in the sense
    Accelerated C++ means in tha above statement.

    > return 0;
    > };


    > Then I found out each element in a has it's "x" value as 0.


    Or something else. The initial value is not specified, and any
    attempt to read it is undefined behavior, so you could end up
    with everything 0. You could also end up with values that cause
    a core dump when read, if such exist on the machine in question.

    > I think
    > this is what the author of the book meant. Then I tried another
    > example:


    > int main(){
    > int b[10];
    > return 0;
    > }


    You're reading Accelerated C++, right? Doesn't that book
    normally use std::vector<int> for arrays?

    > This time, each element in b has garbage value. Isn't each member of
    > b supposed to be value-init to 0?


    There's no difference in your two examples. In both cases, the
    objects are simply not initialized.

    --
    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, May 2, 2007
    #2
    1. Advertising

  3. Jess

    Jess Guest

    On May 3, 1:26 am, James Kanze <> wrote:
    > Don't feel bad. The definitions for these two have changes
    > several times. The simplest solution for the everyday use is to
    > consider them synonyms, and not worry about the subtle
    > differences. If you design your classes correctly, they
    > shouldn't really be relevant anyway.


    Thank you so much for your detailed explanations, really helpful to
    me. :) I'll make sure to initialize everything, but sometimes I'd
    have to build on existing programs written by other people, and
    there's no guarantee their programs init every thing properly...

    > > a. if it's created by invoking a constructor like "T t(arg)", then all
    > > its POD member gets initialized according to the constructor
    > > initializer; any POD member not mentioned gets value-init to 0.

    >
    > No. If the object has static storage duration, it will be
    > initially zero initialized, and then the constructor will be
    > called, otherwise, the constructor will be called directly.


    So if T is a class type then "static T t(args)" zero-init t and then
    calls the constructor again? Moreover, zero-init "t" will set all POD
    members of "t" to zero, is this right?

    > > But
    > > what happens to those class-typed members? Are their default
    > > constructors (or synthesized one) called? I think after all these are
    > > done, the constructor's body is entered.

    >
    > All constructors systematically call the constructors of all
    > sub-objects, if those sub-objects have a non-trivial
    > constructor.


    If there's no default constructor, will the compiler call the
    synthesized version?

    > Attention: this is NOT a container, at least not in the sense
    > Accelerated C++ means in tha above statement.
    >


    I see, so container really has to be the library-defined container,
    rather than the primitive arrays, which are kind of container (in the
    sense that they store objects).

    > You're reading Accelerated C++, right? Doesn't that book
    > normally use std::vector<int> for arrays?


    Yes, it uses vectors as arrays most of the time, until it reaches the
    pointers-arrays chapter. This reminds me of another question. The
    book says if I use "new T[n]", then we must be able to default-init
    "T", otherwise the compiler will reject it. I tried both POD types
    (int) and also object types, and neither was rejected by the
    compiler. What does the author really mean? Moreover, if "T" is
    char, then the array looks like a sequence of '\0', and if T is int,
    then it's a sequence of 0. So, I guess it does zero-init to all the
    objects in the array...

    Thanks!
    Jess
     
    Jess, May 3, 2007
    #3
  4. Jess

    James Kanze Guest

    On May 3, 2:29 am, Jess <> wrote:
    > On May 3, 1:26 am, James Kanze <> wrote:


    > > Don't feel bad. The definitions for these two have changes
    > > several times. The simplest solution for the everyday use is to
    > > consider them synonyms, and not worry about the subtle
    > > differences. If you design your classes correctly, they
    > > shouldn't really be relevant anyway.


    > Thank you so much for your detailed explanations, really helpful to
    > me. :) I'll make sure to initialize everything, but sometimes I'd
    > have to build on existing programs written by other people, and
    > there's no guarantee their programs init every thing properly...


    I know the feeling:). I often have to build on code which has
    a lot of undocumented preconditions too.

    > > > a. if it's created by invoking a constructor like "T t(arg)", then all
    > > > its POD member gets initialized according to the constructor
    > > > initializer; any POD member not mentioned gets value-init to 0.


    > > No. If the object has static storage duration, it will be
    > > initially zero initialized, and then the constructor will be
    > > called, otherwise, the constructor will be called directly.


    > So if T is a class type then "static T t(args)" zero-init t and then
    > calls the constructor again? Moreover, zero-init "t" will set all POD
    > members of "t" to zero, is this right?


    Yup.

    Generally, it's not something you can count on, because when you
    write the class, you cannot guarantee that all instances will
    have static lifetime. There are a few exceptions, however, and
    I've written one or two classes (in over 15 years of C++) which
    depended on zero initialization. I'd consider such things to be
    "tricky code", however, only to be used if absolutely necessary,
    and then only be experienced programmers.

    > > > But
    > > > what happens to those class-typed members? Are their default
    > > > constructors (or synthesized one) called? I think after all these are
    > > > done, the constructor's body is entered.


    > > All constructors systematically call the constructors of all
    > > sub-objects, if those sub-objects have a non-trivial
    > > constructor.


    > If there's no default constructor, will the compiler call the
    > synthesized version?


    If there is one. (If there isn't any code which requires the
    default constructor is illegal.) There are two distinctions
    between constructors: trivial vs. non-trivial, and user defined
    vs. implicit. All user defined constructors are considered
    non-trivial, but implicitly defined constructors can also be
    non-trivial: if the class has a sub-component with a non-trivial
    constructor, or virtual functions, or a virtual base, the
    compiler generated constructor is also non-trivial. A class
    with a non-trivial constructor is not a POD. Generally
    speaking, if a class is not a POD, the constructor is
    responsible for all initializations. If the compiler generated
    default constructor doesn't do what is wanted, then the author
    of the class has the responsibility of writing one.

    In practice, I think that there is also a distinction between
    "agglomerates" and other classes. If a type (class or C-style
    array) is an agglomerate, you can (and generally should)
    initialize it using the "{...}" syntax. If a class isn't an
    agglomerate, the only initialization possible is through the
    constructors; if they don't do an adequate job, the class is
    unusable.

    > > Attention: this is NOT a container, at least not in the sense
    > > Accelerated C++ means in tha above statement.


    > I see, so container really has to be the library-defined container,
    > rather than the primitive arrays, which are kind of container (in the
    > sense that they store objects).


    Everything is a kind of container, if you want, since everything
    contains at least one object (and everything contains some
    number of bits). But the usual meaning of "container" in C++
    doesn't include C style arrays, although you're right that it
    could, logically.

    > > You're reading Accelerated C++, right? Doesn't that book
    > > normally use std::vector<int> for arrays?


    > Yes, it uses vectors as arrays most of the time, until it reaches the
    > pointers-arrays chapter. This reminds me of another question. The
    > book says if I use "new T[n]", then we must be able to default-init
    > "T", otherwise the compiler will reject it. I tried both POD types
    > (int) and also object types, and neither was rejected by the
    > compiler. What does the author really mean?


    I'm not sure, but I suspect that he's using default initialize
    in a more general sense: using the strict definition in the
    standard, "new T[n]" does not default initialize the objects.
    If the object type T is not a POD, it calls the default
    constructor (which must be accessible); otherwise, the object is
    not initialized (and type T may not be const qualified).

    > Moreover, if "T" is char, then the array looks like a sequence
    > of '\0', and if T is int, then it's a sequence of 0. So, I
    > guess it does zero-init to all the objects in the array...


    Not at all.

    Be very careful about what you see in tests. On a lot of
    systems (most?), memory just received from the OS will be
    zeroed, for security reasons. In most cases, operator new (and
    allocation of local variables) just hands out the memory, with
    whatever values it happens to have. If you write a small test,
    which just does one allocation, then looks at the values,
    there's a good chance that they are 0, the same as if you only
    call one function, and look at a few local variables in it. In
    a real application, on the other hand, memory is constantly
    being allocated and freed, and in most implementations, what you
    get when the memory is allocated is whatever whoever used it
    before left there---just random junk, for all intents and
    purposes. (When developing code, I use a special operator new,
    which fills the memory with an easily identifiable non-zero
    value, so that if I forget initialization, the program will
    probably fail immediately, and looking at the objects, it will
    be recognizable that there was no initialization.)

    --
    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, May 3, 2007
    #4
  5. Jess

    Jess Guest

    On May 3, 6:24 pm, James Kanze <> wrote:...


    Many thanks for clarifying the matter! :)

    Jess
     
    Jess, May 4, 2007
    #5
    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. Tony Cheng
    Replies:
    1
    Views:
    8,218
    Juan T. Llibre
    Feb 24, 2006
  2. JKop
    Replies:
    10
    Views:
    949
  3. Replies:
    1
    Views:
    664
    Jules
    Aug 18, 2005
  4. Jess
    Replies:
    23
    Views:
    933
  5. Taras_96
    Replies:
    3
    Views:
    589
    Michael Tsang
    Oct 30, 2009
Loading...

Share This Page