问题
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 = { };
}
回答1:
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, thenS()
is value-initialization butS{}
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.
来源:https://stackoverflow.com/questions/59887383/difference-between-s-vs-s