Влияет ли знак равенства на инициализацию фигурной скобки? например. «T a = {}» против «T a {}»

Вот два способа инициализировать переменную в C++11:

T a {something};
T a = {something};

Я проверил эти два во всех возможных сценариях и не заметил разницы. Этот ответ предполагает, что между ними есть тонкая разница:

Для переменных я не обращаю особого внимания между стилями T t = { init }; или T t { init };, я нахожу разницу незначительной и в худшем случае приведет только к полезному сообщению компилятора о неправильном использовании явного конструктора.

Итак, есть ли разница между ними?


person Nikita    schedule 22.12.2013    source источник
comment
Отвечает ли это на ваш вопрос? Почему инициализация списка (с использованием фигурных скобок) лучше чем альтернативы?   -  person user202729    schedule 29.01.2021
comment
@user202729 user202729 Я не смог найти там ответа. В принятом ответе говорится об сужающих ограничениях, которые возникают со знаком равенства и без него.   -  person Nikita    schedule 31.01.2021
comment
... вопрос требует в основном одного и того же, но из-за разной формулировки они привлекают разные ответы. Не помешает связать это здесь.   -  person user202729    schedule 31.01.2021
comment
(кстати, это сообщение автоматически генерируется для флага дублирования)   -  person user202729    schedule 31.01.2021


Ответы (1)


Единственное существенное отличие, которое я знаю, заключается в обработке конструкторов explicit:

struct foo
{
    explicit foo(int);
};

foo f0 {42};    // OK
foo f1 = {42};  // not allowed

Это похоже на «традиционную» инициализацию:

foo f0 (42);  // OK
foo f1 = 42;  // not allowed

См. [over.match.list]/1.


Кроме того, есть дефект (см. CWG 1270) в C ++11, который допускает скобочное исключение только для формы T a = {something}

struct aggr
{
    int arr[5];
};

aggr a0 = {1,2,3,4,5};  // OK
aggr a1 {1,2,3,4,5};    // not allowed
person dyp    schedule 22.12.2013
comment
Разве a = {что-то} не приводит к дополнительному копированию/перемещению? - person gvd; 23.12.2013
comment
@gvd Нет, вот чем отличается традиционная копия-инициализация и копия-списка-инициализации: foo f0 = 42; преобразует 42 во временное значение prvalue foo и напрямую инициализирует f0 с этим временным (посредством, возможно, пропущенной копии/перемещения), тогда как foo f1 = {42}; выбирает конструктор из f1 для вызова с 42 (в этом случае можно удалить ctor copy+move). - person dyp; 23.12.2013