Are = {} и {} -истовые инициализации одинаковы в С++ 11?

С++ 11 представил {} -истинные инициализации. Но эти две формы

T x {...};
T x = {...};

то же самое?

Ответ 1

Они не совсем то же самое. Может быть, это можно проиллюстрировать на примере:

struct Foo
{
  explicit Foo(std::initializer_list<int>) {}
};

int main()
{
  Foo f0{1, 2, 3};    // OK
  Foo f1 = {1, 2, 3}; // ERROR
}

Итак, второй вариант требует, чтобы тип был неявно конструктивным из списка инициализации, тогда как в первой версии этого нет. Заметим, что то же самое относится и к конструкторам формы Foo(int, int, int). Я выбрал initializer_list<int> в качестве примера произвольно.

Это повлияет на определенные типы, написанные в соответствии с философией "явной во всем мире" (в которой люди отмечают многопараметрические конструкторы explicit в коде С++ 03, даже если это не имеет смысла в этом стандарте.)

Ответ 2

В дополнение к различию, объясненному в juanchopanza answer, существует другая разница, нарушение изменения между инициализацией прямого списка и инициализацией списка копий, когда оно доходит до auto и выводит вывод скопированного-init-списка. Хотя он был не добавлен как часть С++ 14 (последний элемент Q & A), проблема была идентифицирована, и это зависит от комитет, когда он будет реализован.

Например,

auto foo = {42};  // deduces foo as an initializer_list<int>
auto foo{42};     // deduces foo as an int

Таким образом, инициализация прямого списка никогда не выводит initializer_list из аргумента. Следовательно, следующее будет плохо сформировано.

auto foo{1,2};    // cannot have multiple initializers for 
                  // direct-list-initialization when deducing type

Но это нормально:

auto foo = {1,2}; // copy-list-initialization still deduces initializer_list<int>

То же самое относится к обобщенным захватам в лямбда-выражениях. Цитирование N3912

[x{5}](){};        // x is int
[x{1,2}](){};      // ill-formed, no multiple initializers with direct-init
[x = {5}](){};     // ok, x is an initializer_list<int> with one element
[x = {1,2}](){};   // ok, x is an initializer_list<int> with two elements

Ответ 3

Синтаксис при их использовании в одном случае означает разные вещи

struct A { };

namespace X {
  struct A final {};
  struct A final = {};
}

В первом случае мы определяем структуру с именем A, а во втором случае мы определяем объект с именем final.