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

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

первый:

int abc = 7;

второй:

int abc {7};

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

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

2 ответов


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

инициализация через {..} является инициализацией списка, которая запрещает сужение конверсий. Например, если 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

а именно с {..} использовать инициализацию списка. The {..} называется braced-init-list.

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

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

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

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

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

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

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

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


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

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