Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between S() vs S{}?

In the code below, is there any difference between the two assignments to value? In both cases, would value.v be default constructed, and x be initialized to 42?

struct S
{
   std::vector<int> v;
   int x = 42;
};
S value;

void foo()
{
   value = S();
   value = { };
}
like image 969
Steve Avatar asked Jan 23 '20 21:01

Steve


Video Answer


1 Answers

S() and S{} mean the same thing in nearly all cases. But not all cases.

  • If S is not a class type, same thing: value initialization.
  • If S is a class type that is not an aggregate, still mostly means the same thing: value initialization. Except in cases like:

    struct X { X(std::initializer_list<int>); };
    auto x1 = X(); // ill-formed
    auto x2 = X{}; // ok, calls constructor
    
  • if S is an aggregate, then S() is value-initialization but S{} s aggregate-initialization. Even that means the same thing a lot of the time. But not all of the time.

Example 1: explicit default constructor makes aggregate-initialization ill-formed

struct A { explicit A(int = 0); };
struct B { A a; };

B b;        // OK
B b2 = B(); // OK
B b3{};     // error through trying to copy-list-initialize a = {}

Example 2: value initialization in some contexts does zero-initialization first

struct C { C() {} int i; };
struct D { C a; }; 

D d1{};     // d1.a.i is indeterminate
D d2 = D(); // d2.a.i is zero

In the OP example though, while S is an aggregate with an implicitly-defined default constructor - this is the interesting case. But here, there's no change in semantics with the extra zero-initialization, we're initializing x to 42 and default-constructing v either way.


Note that also while in OP, this invokes (and is intended to invoke) the move assignment operator from S{}:

value = { };

it's also possible that this could invoke a different operator entirely, since {} could end up binding "better" to some different parameter in a different assignment operator overload. std::optional has to jump through some hooks to ensure that opt = {} actually invokes the move assignment operator.

like image 172
Barry Avatar answered Oct 21 '22 23:10

Barry