Разница между S () и S {}?

В приведенном ниже коде есть ли разница между двумя присвоениями значения? В обоих случаях будет ли value.v создан по умолчанию, а x будет инициализирован равным 42?

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

void foo()
{
   value = S();
   value = { };
}

person Steve    schedule 23.01.2020    source источник
comment
Почему бы не попробовать?   -  person Ruslan    schedule 24.01.2020
comment
У меня есть. В MSVC я получаю такое же поведение. Однако в моей целевой системе, встроенной платформе с RTOS, я получаю системный сбой, когда использую синтаксис { }. Было непросто отследить, где именно произошел сбой, потому что это произошло во время запуска системы, прежде чем я смог подключить удаленный отладчик к плате процессора. Однако после изменения синтаксиса некоторых моих кодов инициализации на более старый стиль конструктора моя плата загружается без происшествий. Таким образом, это привело меня к вопросу, правильно ли я понимаю поведение двух утверждений.   -  person Steve    schedule 24.01.2020
comment
Стив помогает? cppinsights.io/s/bee58611   -  person NoSenseEtAl    schedule 24.01.2020
comment
Кажется, я подтверждаю, что я ожидал, что результат должен быть эквивалентным? Однако эта ссылка весьма полезна, спасибо!   -  person Steve    schedule 24.01.2020
comment
См. раздел Инициализация — cppreference.com.   -  person David C. Rankin    schedule 24.01.2020
comment
@Ruslan, пытающийся это сделать, не поможет узнать, является ли поведение стандартным, зависимым от компилятора или неопределенным.   -  person M.M    schedule 24.01.2020


Ответы (1)


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
comment
@DavidC.Rankin Да. Да, это так. :-( - person Barry; 24.01.2020
comment
Если S является типом класса, который не является агрегатом, по-прежнему означает то же самое - верно ли это, даже если S имеет конструктор списка инициализаторов? - person M.M; 24.01.2020
comment
@M.M Да, маркер value-initialize предшествует std::initializer_list. - person Barry; 24.01.2020
comment
Вы пропустили случай, когда S не имеет конструктора по умолчанию, но имеет конструктор списка инициализаторов. - person T.C.; 25.01.2020
comment
Интересно, что вы упомянули о std::Optional, потому что в моем реальном случае у меня было несколько членов std::Optional в S! - person Steve; 28.01.2020