The default ctor values ​​between gcc 4.6 and 4.7

In GCC 4.6.1, when I declare an instance of my own type that has a default constructor, and if I instantiate an object of this type and initialize it with curly braces (for example, Foo my_foo {};), the POD members in this class there will only be zero initialization unless another constructor is declared. If there is no constructor other than the default one, it will be null as expected.

But, in GCC 4.7.3, zero initialization happens anyway, this is the behavior I was expecting.

What is the difference here? Is this a compiler error? Both versions of GCC support standard C ++ 11 standard constructors.

There is no real need to stick with older versions of GCC, but I would like to understand what is going on here.

note: I do not execute the main ctor, op =. and copy ctor just to save the type that can be used with variational functions (clang requires that it classify the class as POD, although gcc allowed me to leave using the variational type even with user-defined basic game points, if you can tell me why.)

Here is an example program to illustrate, including some output below (from binaries compiled in both versions of GCC):

#include <cstdio> // pod and pod_wctor are identical except that pod_wctor defines another ctor struct pod { pod( void ) = default; pod( const pod& other ) = default; pod& operator=( const pod& other ) = default; int x,y,z; }; struct pod_wctor { pod_wctor( void ) = default; pod_wctor( const int setx, const int sety, const int setz ) : x(setx), y(sety), z(setz) { } pod_wctor( const pod_wctor& other ) = default; pod_wctor& operator=( const pod_wctor& other ) = default; int x,y,z; }; int main ( void ) { printf("the following shuold be uninitialized:\n"); pod pee; printf( " %i,%i,%i\n", pee.x, pee.y, pee.z); pod_wctor podtor; printf( " %i,%i,%i\n", podtor.x, podtor.y, podtor.z); printf("the following shuold be initialized to 0,0,0:\n"); pod peenit{}; printf( " %i,%i,%i\n", peenit.x, peenit.y, peenit.z ); pod_wctor podtornit{}; printf( " %i,%i,%i\n", podtornit.x, podtornit.y, podtornit.z ); return 0; } // compiled with: g++ m.cpp -std=gnu++0x // g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1 (i386) /****************** output ******************* the following shuold be uninitialized: 10381592,134513249,134520820 134513969,134513504,0 the following shuold be initialized to 0,0,0: 0,0,0 7367877,134513945,8724468 *********************************************/ // compiled with: g++ m.cpp -std=gnu++0x // gcc version 4.7.3 (Ubuntu/Linaro 4.7.3-2ubuntu4) (i386) /****************** output ******************* the following shuold be uninitialized: -1218358300,-1217268232,134520832 134514450,1,-1079827548 the following shuold be initialized to 0,0,0: 0,0,0 0,0,0 *********************************************/ 
+6
source share
1 answer

Adding the constructor pod_wctor( const int setx, const int sety, const int setz ) : x(setx), y(sety), z(setz) { } to your class, it loses its status as a collection: [dcl.init.aggregate ]/1

An aggregate is an array or class (section 9) without the constructors provided by the user

It is still a POD, because the trivial class must have non-trivial default ctors: [class] / 6

A trivial class is a class that has a default constructor (12.1), does not have non-trivial default constructors, and can be trivially copied.


An interesting point here is that for an aggregate, initializing a list is pod peenit{}; performs aggregate initialization:

An initialization list of an object or link of type T is defined as follows:

  • If T is an aggregate, aggregate initialization is performed (8.5.1). [...]
  • Otherwise, if there are no elements in the initializer list, and T is the class type with the default constructor, the object is initialized with a value.

(Note: this is a corrected order. AFAIK, in the standard itself, the order of these two points is canceled, which should be a defect, since each unit has a default value of ctor - implicitly declared and defined.)

Aggregate initialization initializes the value of int members: [dcl.init.aggr] / 7

If there are fewer initializer sentences in the list than in the aggregate, then each member that is not explicitly initialized should be initialized from an empty initialization list

and [dcl.init.list] / 3 "Otherwise, if there are no elements in the initializer list, the object is initialized with the value"


However, for a non-pod_wctor pod_wctor initializing the pod_wctor podtornit{} list pod_wctor podtornit{} directly initializes the value, which calls the default value ctor. [class.ctor] / 6 indicates:

An implicit default constructor executes a set of class initializations that will be executed by a user-written default constructor for this class without the ctor initializer (12.6.2) and an empty compound statement.

and in [class.base.init] / 8 we find:

In the constructor without delegation, if the given non-static data element or base class is not indicated by the mem-initializer identifier (including the case when there is no mem-initializer list, since the constructor does not have ctor-initializer), and the entity is not a virtual base class of the abstract class (10.4 ) then

  • [...]
  • otherwise, the object is initialized by default (8.5).

By default, ctor itself does not guarantee nullification of members, since it only initializes members by default.


Difference between default initialization and value: [dcl.init]

[7] By default, to initialize an object of type T means:

  • If T is (possibly cv-qualit) a class type, the default constructor for T is called [...]
  • [...]
  • otherwise, initialization fails.

[...]

[8] To initialize a value of an object of type T means:

  • if T is a (possibly cv-qualified) class type without a default constructor or a default constructor that is provided or deleted by the user, then the object is initialized by default;
  • If T is a (possibly cv-qualified) class of non-union type without a user-created or remote default constructor, then the object is initialized to zero, and if T has a non-trivial default constructor, initialized by default;
  • [...]
  • otherwise, the object is initialized to zero.

(I admit that this confused me, and I had to revise my answer.)

pod_wctor has a default constructor that is not provided to users. Therefore, to initialize the list pod_wctor podtornit{} , a second value initialization bullet is used. The podtornit object podtornit initialized to zero, which results in zero initialization of its members. Only then will it be initialized by default, and ctor will be called by default. The latter does nothing, but the former ensures that members are zeroed out.

+2
source

Source: https://habr.com/ru/post/954192/


All Articles