S()
и S{}
почти во всех случаях означают одно и то же. Но не во всех случаях.
- Если
S
не является типом класса, то же самое: инициализация значения.
Если S
является типом класса, который не является агрегатом, это по большей части означает одно и то же: инициализацию значения. За исключением таких случаев, как:
struct X { X(std::initializer_list<int>); };
auto x1 = X(); // ill-formed
auto x2 = X{}; // ok, calls constructor
если S
— агрегат, то S()
— это инициализация значения, а S{}
— инициализация агрегата. Даже это означает одно и то же в большинстве случаев. Но не все время.
Пример 1: явный конструктор по умолчанию делает агрегатную инициализацию неправильной
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 = {}
Пример 2: при инициализации значения в некоторых контекстах сначала выполняется нулевая инициализация
struct C { C() {} int i; };
struct D { C a; };
D d1{}; // d1.a.i is indeterminate
D d2 = D(); // d2.a.i is zero
Однако в примере OP, хотя S
является агрегатом с неявно определенным конструктором по умолчанию, это интересный случай. Но здесь нет никаких изменений в семантике с дополнительной нулевой инициализацией, мы инициализируем x
в 42
и строим по умолчанию v
в любом случае.
Обратите внимание, что также в OP это вызывает (и предназначено для вызова) оператор присваивания перемещения из S{}
:
value = { };
также возможно, что это может вызвать совершенно другой оператор, поскольку {}
может в конечном итоге привязать «лучше» к какому-то другому параметру в другой перегрузке оператора присваивания. std::optional
должен пройти через несколько перехватов, чтобы убедиться, что opt = {}
действительно вызывает оператор присваивания перемещения.
person
Barry
schedule
24.01.2020