Подтвердить что ты не робот

Разница инициализации с или без фигурных скобок в С++ 11

Мы можем инициализировать переменную двумя способами в С++ 11

Один:

int abc = 7;

Два:

int abc {7};

В чем разница между этими двумя методами?

Как компилятор рассматривает их по-другому или как эти коды выполняются?

4b9b3361

Ответ 1

Краткая версия

Инициализация через {..} - это инициализация списка, которая запрещает сужение конверсий. Например, если LLONG_MAX - максимальное значение long long int, а ваш int не может представлять это:

int x = LLONG_MAX;  // probably accepted with a warning
int x {LLONG_MAX};  // error

Аналогично:

long long y = /*something*/;

int x = y;  // accepted, maybe with a warning
int x {y};  // error

Длинная версия

Инициализация формы

T x = a;

- копирование; инициализация любой формы

T x(a);
T x{a};

- прямая инициализация, [dcl.init]/15-16.

[dcl.init]/14 затем говорит:

Форма инициализации (с использованием круглых скобок или =) обычно несущественна, но имеет значение, когда инициализатор или инициализируемый объект имеет тип класса; см. ниже.

Итак, для типов неклассов форма инициализации не имеет значения. Однако существует разница между этими двумя прямыми инициализациями:

T x(a);  // 1
T x{a};  // 2

и аналогично между этими двумя инициализациями копирования:

T x = a;    // 1
T x = {a};  // 2

А именно, те, у которых {..}, используют инициализацию списка. {..} называется скобкой-init-list.

Итак, когда вы сравниваете T x = a; с T x {a};, существуют два отличия: copy-vs. direct-initialization и "non-list-" vs. list-initialization. Как уже упоминалось другими и в приведенной выше цитате, для неклассовых типов T нет никакой разницы между copy- и direct-init. Однако существует разница между list-init и no-list-init. То есть, мы могли бы сравнить

int x (a);
int x {a};

Инициализация списка в этом случае запрещает сужение конверсий. Сужение конверсий определено в [dcl.init.list]/7 как:

Сужение преобразования является неявным преобразованием

  • от типа с плавающей точкой до целочисленного типа или

  • от long double до double или float или от double до float, за исключением случаев, когда источник является константным выражением, а фактическое значение после преобразования находится в диапазоне значений, которые могут быть представлены (даже если он не может быть представлен точно), или

  • от целочисленного типа или типа неперечисленного перечисления до типа с плавающей точкой, за исключением случаев, когда источник является постоянным выражением, а фактическое значение после преобразования будет соответствовать типу цели и будет выведите исходное значение при преобразовании обратно в исходный тип или

  • из целочисленного типа или типа неперечисленного перечисления в целочисленный тип, который не может представлять все значения исходного типа, за исключением случаев, когда источником является постоянное выражение, значение которого после интеграла рекламные акции будут вписываться в целевой тип.

Ответ 2

Первая - это инициализация копирования, а вторая - инициализация списка.

Но обычно инициализация копирования менее используется. Поскольку, если вы делаете это, передавая объекты определенных пользователем типов, он просто вызывает биткопию и, следовательно, не может давать намеченные результаты, если пользовательский класс использует указатели.