Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++14 Uniform Initialization on a Non-Aggregate

I'm using Visual C++ 2013. When the class is an aggregate it is zero-initialized. When it's a non-aggregate it seems to be default-initialized and left indeterminate. Why is that?

#include <iostream>

using namespace std;

class Test_1
{
public:
    int i;
    void f(){};
};

class Test_2
{
public:
    int i;
    virtual void f(){};
};

int main()
{
    Test_1 t1{};
    Test_2 t2{};

    cout<<t1.i<<endl; //0
    cout<<t2.i<<endl; //-858993460

    getchar();
}
like image 412
SelymAI Avatar asked Sep 28 '22 19:09

SelymAI


1 Answers

If your compiler is doing this, it's broken.

[dcl.init.list]/p3 (all quotes are from N4140):

List-initialization of an object or reference of type T is defined as follows:

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

[dcl.init]/p8:

To value-initialize an object of type T means:

  • if T is a (possibly cv-qualified) class type (Clause 9) with either no default constructor (12.1) or a default constructor that is user-provided or deleted, then the object is default-initialized;
  • if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
  • if T is an array type, then each element is value-initialized;
  • otherwise, the object is zero-initialized.

Test_2 is not an aggregate, so t2 should have been value-initialized. In turn, since Test_2's default constructor is not user-provided, t2 is supposed to be first zero-initialized (causing t2.i to be initialized to 0), and then the default constructor is run.

like image 136
T.C. Avatar answered Oct 06 '22 01:10

T.C.