Default value and zero

I am very confused about initializing values ​​and defaults and zeros. and especially when they kick for different standards C ++ 03 and C ++ 11 (and C ++ 14).

I am quoting and trying to extend a really good Value- / Default- / Zero-Init answer C ++ 98 and C ++ 03 to make this more general, as it would help many users if someone could help fill in the required spaces to have a good overview of what happens when?

A complete description of the examples in a nutshell:

Sometimes the memory returned by the new operator will be initialized, and sometimes it does not depend on whether the type you are new to is POD (plain old data) , or if it is a class containing POD elements and uses the default constructor created by the compiler.

  • In C ++ 1998, there are 2 types of initialization: zero and default
  • In C ++ 2003, a third type of initialization was added, value initialization.
  • In C ++ 2011 / C ++ 2014, only list initialization was added, and the rules for initializing value / default // zero have changed a bit.

Assume

struct A { int m; }; struct B { ~B(); int m; }; struct C { C() : m(){}; ~C(); int m; }; struct D { D(){}; int m; }; struct E { E() = default; int m;} /** only possible in c++11/14 */ struct F {F(); int m;} F::F() = default; /** only possible in c++11/14 */ 

In the C ++ 98 compiler, the following should happen ::

  • new value A - undefined value (A - POD)
  • new A () - zero-initialize
  • new B - default construction (B :: m is not initialized, B is not a POD)
  • new B () - default construct (B :: m not initialized)
  • new default C construction (C :: m is initialized to zero, C is not a POD)
  • new C () - default construct (C :: m is initialized to zero)
  • new D is the default constructor (D :: m is not initialized, D is not a POD)
  • new D () - default construct? (D :: m is not initialized)

In a compiler compatible with C ++ 03, everything should work like this:

  • new value A - undefined value (A - POD)
  • new A () - initialize the value of A, which is zero initialization, since it is a POD.
  • new B - initializes by default (leaves B :: m uninitialized, B is not a POD)
  • new B () - the value initializes B, which zero initializes all fields, since by default ctor is generated by the compiler, unlike the user-defined one.
  • new C - default - initializes C, which calls the default value ctor. (C :: m is initialized to zero, C is not a POD)
  • new C () - the value initializes C, which calls the default value ctor. (C :: m is initialized to zero)
  • new D is the default constructor (D :: m is not initialized, D is not a POD)
  • new D () - the value initializes D?, which calls the default value ctor (D :: m is not initialized)

Italic meanings and? are uncertainties, please help fix this :-)

In a compiler compatible with C ++ 11, everything should work like this:

??? (please help if I start here, it will still go wrong)

In a compiler compatible with C ++ 14, everything should work like this: ??? (please help if I start here, it will still go wrong) (The project is based on the answer)

  • new A - default - initializes A, the gen compiler. ctor, (leavs A :: m uninitialized) (A - POD)
  • new A () - the value initializes A, which is zero initialization, since 2. point in [dcl.init] / 8

  • new B - by default initializes B, the gen compiler. ctor, (leavs A :: m uninitialized) (B is not a POD)

  • new B () - the value initializes B, which zero initializes all fields, since by default ctor is generated by the compiler, unlike the user-defined one.
  • new C - default - initializes C, which calls the default value ctor. (C :: m is initialized to zero, C is not a POD)
  • new C () - the value initializes C, which calls the default value ctor. (C :: m is initialized to zero)
  • new D - default initialization D (D :: m is not initialized, D is not a POD)
  • new D () - the value initializes D, which calls the default value ctor (D :: m is not initialized)
  • new E - default - initializes E, which calls comp. generations. te (D :: m is not initialized, D is not a POD)
  • new E () - the value initializes E, which zero initializes E, since 2 points in [dcl.init] / 8)
  • new F - default - initializes F, which calls comp. generations. te (D :: m is not initialized, D is not a POD)
  • new F () - the value initializes F, which by default initializes F with 1. point in [dcl.init] / 8 (a function is provided by the user if it is declared by the user and is clearly not defaulted or deleted by its first declaration. Link )
+67
c ++ c ++ 11 c ++ 03 c ++ 14 c ++ 98
Apr 21 '15 at 7:44
source share
2 answers

C ++ 14 indicates the initialization of objects created with new in [expr.new] / 17 ([expr.new] / 15 in C ++ 11, and the note was not a note, but the normative text is back then):

A new expression that creates an object of type T initializes this object as follows:

  • If the new initializer is omitted, the object is initialized by default (8.5). [Note: if no initialization is performed, the object has an undefined value. - final note]
  • Otherwise, the new-initializer is interpreted in accordance with 8.5 initialization rules for direct initialization.

The default initialization is defined in [dcl.init] / 7 (/ 6 in C ++ 11, and the wording itself has the same effect):

To initialize an object of type T by default:

  • If T is a (possibly cv-qualified) class type (section 9), the default constructor (12.1) is called for T (and initialization is poorly formed if T does not have a default constructor or overload resolution (13.3) leads to ambiguity or a function that is removed or inaccessible from the initialization context);
  • if T - array type, each element is initialized by default;
  • otherwise, initialization fails.

In this way,

  • new A calls only the default constructor of A by default, which does not initialize m . Undefined value. Must be the same for new B
  • new A() interpreted according to [dcl.init] / 11 (/ 10 in C ++ 11):

    An object whose initializer is an empty set of brackets, i.e. () must be initialized with a value.

    Now consider [dcl.init] / 8 (/ 7 in C ++ 11 †):

    To initialize a value of an object of type T means:

    • if T is a (possibly cv-qualified) type of class (section 9) without a default constructor (12.1) or a default constructor that is user-supplied or deleted, then the object is initialized by default;
    • if T is (possibly cv-qualit) a class type without a user-supplied or removable default constructor, then the zero-initialization object and semantic constraints are checked for default initialization, and if T has a non-trivial default constructor, the object is initialized by default;
    • If T is an array type, then each element is initialized with a value;
    • otherwise, the object is initialized to zero.

    Therefore, new A() will be initialized to zero m . And that should be equivalent for A and B

  • new C and new C() will by default initialize the object again, since the first marker point from the last quote is used (C has a default user-supplied constructor!). But, obviously, now m initialized in the constructor in both cases.




† Well, this paragraph has a slightly different wording in C ++ 11, which does not change the result:

To initialize a value of an object of type T means:

  • if T is a (possibly cv-qualified) class (section 9) with a user-provided constructor (12.1), then the default constructor for T (and initialization is poorly formed if T does not have an accessible default constructor);
  • if T is a (possibly cv-qualified) non-unit class type without a user-created constructor, then the object is null-initialized and if T s an implicitly declared default constructor is nontrivial, this constructor is called.
  • if T is an array type, then each element is initialized with a value;
  • otherwise, the null object is initialized.
+20
Apr 21 '15 at 7:56
source share

The following answer extends the answer to https://stackoverflow.com/a/2129442/2126 which will serve as a reference for C ++ 98 and C ++ 03

Quoting an answer

  • In C ++ 1998, there are 2 types of initialization: zero and default
  • In C ++ 2003, type 3 initialization, value initialization has been added.

C ++ 11 (link to n3242)

Initializers

8.5 The [dcl.init] initializers indicate that a POD or non POD variable can be initialized either as a copied or equal-initializer, which can be either an init-list bit or an initializer-clause aggregated as a bracket-or -equal-initializer or using (expression list). Previously, in C ++ 11, only (a list of expressions) or the initializer clause was supported, although the initializer clause was more limited than what we have in C ++ 11. In C ++ 11, the initializer clause now supports the init-list bit. in addition to the destination expression, as it was in C ++ 03. The following grammar summarizes the new supported sentence, where this part is in bold, added to the C ++ 11 standard.

initializer:
& nbsp & nbsp & nbsp & nbsp bracket or equal-initializer
& nbsp & nbsp & nbsp & nbsp & nbsp (expression list)
<b> bracket or equal-initializer:
& nbsp & nbsp & nbsp = initializer-clause
& nbsp & nbsp & nbsp & nbsp braced-init-list
initializer-item:
& nbsp & nbsp & nbspassignment-expression
& nbsp & nbsp & nbsp & nbsp braced-init-list
<b> initializer-list:
& nbsp & nbsp & nbsp & nbsp initializer-clause ... opt
& nbsp & nbsp & nbsp & nbsp list of initializers, initializer-clause ... opt **
braced-init-list:
& nbsp & nbsp & nbsp & nbsp {initializer-list, opt}
& nbsp & nbsp & nbsp {}

Initialization

Like C ++ 03, C ++ 11 still supports three forms of initialization




Note

The part in bold was added in C ++ 11, and the one that was struck out was removed from C ++ 11.

  • Initializer Type: 8.5.5 [dcl.init] _zero-initialize_

It is carried out in the following cases

  • Objects with static or stream zero storage are initialized
  • If the number of initializers is less than the elements of the array, each element not explicitly initialized must be initialized to zero
  • During value initialization, if T is a (possibly cv-qualified) non-union class without a user-supplied constructor, then the object is initialized to zero.

For zero initialization of an object or reference of type T means:

  • if T is the scalar type (3.9), the object is set to the value 0 (zero) , taken as an integral expression of the constant converted to T;
  • if T is a class (possibly cv-qualit) that is not the only class, each non-static data element and each subobject of the base class is initialized to zeros , and padding is initialized to zero bits;
  • if T is a union type (possibly cv-qualified) , the objects of the first non-static named data element are initialized to zero , and padding is initialized to zero bits;
  • if T is an array type, each element is initialized to zero;
  • if T is a reference type, initialization is not performed.

2. Initializer type: 8.5.6 [dcl.init] _default-initialize _

It is carried out in the following cases

  • If the new initializer is omitted, the object is initialized by default; if initialization fails, the object has an undefined value.
  • If no initializer is specified for the object, the object is initialized by default, with the exception of objects with a static or storage duration
  • When the base class or non-static data element is not mentioned in the list of constructor initializer and this constructor is called.

To initialize an object of type T by default:

  • if T is a non-POD (possibly cv-qualified) class ( section 9), the default constructor for T is called (and initialization is poorly formatted if T does not have an available default constructor);
  • if T is an array type, each element is initialized by default;
  • otherwise, initialization fails.



Note Before C ++ 11, only non-POD class types with automatic storage duration were considered initialized by default when no initializer was used.




3. Type of initializer: 8.5.7 [dcl.init] _value-initialize _

  • When an object (named temporary, named variable, dynamic memory or non-static data element) whose initiator is an empty set of parentheses, that is () or curly braces {}

To initialize an object of type type T means:

  • if T is a class (possibly cv-qualified) (section 9) with a user-supplied constructor (12.1), then the default constructor for T is called (and initialization is bad if T has no default constructor available);
  • if T is a (possibly cv-qualified) class of type non-union without a user-supplied constructor , then each non-static data element and component of the base class T is initialized with a value; , then the object is initialized to zero and, if Ts, the implicitly declared default constructor is nontrivial, this constructor is invoked.
  • if T is an array type, then each element is initialized with a value;
  • otherwise, the object is initialized to zero.

So, to summarize

Note The corresponding quote from the standard is in bold.

  • new A: default-initializes (leaves A :: m uninitialized)
  • new A (): Zero-initialize A, because the value-initialized candidate does not have a user-supplied or remote default constructor. if T is a (possibly cv-qualified) class of non-union type without a constructor provided by the user, then the object is initialized to zero, and if the TS implicitly declared default constructor is nontrivial, this constructor is called.
  • new B: default-initializes (leaves B :: m uninitialized)
  • new B (): value-initializes B, which zero initializes all fields; if T is a class type (possibly cv-qualit) (section 9) with a user-provided constructor (12.1), then the default constructor for T is called
  • new C: default - initializes C, which calls the default value ctor. if T is a class of a class (possibly cv-qualit) (section 9), the default constructor for T is called . In addition, if the new initializer is omitted, the object is initialized by default.
  • new C (): the value initializes C, which calls the default value ctor. if T is a class type (possibly cv-qualit) (section 9) with a user-provided constructor (12.1), then the default constructor for T is called. In addition, Object, Initializer is an empty set of brackets, i.e. ( ) must be initialized with the value
+10
Apr 21 '15 at 8:50
source share



All Articles