POD members default initialization without braces
Asked Answered
K

3

6

Given code:

struct Test {
    int a = 1;
    int b = 2;
};

Test test1;
Test test2{};

For test2 I am sure, that test2.a == 1 and test2.b == 2. Is it guaranteed (or not) the same for test1 (without {})?

Karole answered 17/4, 2017 at 16:5 Comment(4)
Yes, it is guaranteed. Why would you think it is not?Berlioz
@Berlioz I'm in doubt. Can you point me to the Standard?Karole
Unless something changed in this regard between 11 and 14 I don't see a reason why would test1 not be set to 1 and 2Berlioz
This is not a POD.Ordinand
B
7

The line

Test test1;

is equivalent to an initialization with a default constructor which, in the absence of a hand-written one with an explicit initialization list and with no Test() = deleted; would end up setting the two members to their specified initial values 1 and 2.

A “default constructor” is a constructor that can be called with no arguments, which is exactly the case with the above statement.

You can read up on the rules for default constructors in the standard - go to § 12.1 section 4:

A default constructor for a class X is a constructor of class X that can be called without an argument...

And further in section 5:

A default constructor that is defaulted and not defined as deleted is implicitly defined when it is odrused (3.2) to create an object of its class type (1.8)...

Berlioz answered 17/4, 2017 at 16:16 Comment(0)
L
6

Yes, they have the same effect here.

For the 1st case, it's default initialization,

if T is a class type, the constructors are considered and subjected to overload resolution against the empty argument list. The constructor selected (which is one of the default constructors) is called to provide the initial value for the new object;

That means the implicitly-defined default constructor will be invoked; it doesn't use any member initializer list and then default member initializer would take effect to initialize the data members.

For the 2nd case, it's aggregate initialization,

If the number of initializer clauses is less than the number of members and bases (since C++17) or initializer list is completely empty, the remaining members and bases (since C++17) are initialized by their default initializers, if provided in the class definition, and otherwise (since C++14) ...

So the default member initializer would take effect to initialize the data members, too.

Larynx answered 17/4, 2017 at 16:21 Comment(2)
@hvd You meant before C++14? (yes before C++14 it becomes value-intialization; and Test is not an aggregate type.)Larynx
I messed up there, sorry. You're right. I got confused in what did and didn't make it into C++14.Caritta
M
4

test1 is also guaranteed to have its member a initialized to 1 and its member b to be initialized to 2.

From C++11 FAQ, In-class member initializers:

The basic idea for C++11 is to allow a non-static data member to be initialized where it is declared (in its class). A constructor can then use the initializer when run-time initialization is needed. Consider:

class A {
  public:
    int a = 7;
};

This is equivalent to:

class A {
  public:
    int a;
    A() : a(7) {}
};
Matchmark answered 17/4, 2017 at 16:7 Comment(2)
This looks like a correct statement to me. I'm curious as to why was it downvoted? Twice!Berlioz
@YePhIcK, The first version of my answer was wrong. I posted an answer without reading the question clearly.Matchmark

© 2022 - 2024 — McMap. All rights reserved.