Ответ 1
Во-первых, я бы рекомендовал посмотреть следующие беседы Herb Sutter, в котором он дает некоторые рекомендации по этому вопросу. Обсуждение инициализации скобки начинается с около 23:00.
Когда вы говорите о примитивных типах данных, все 3 дают одинаковый результат. Я лично предпочитаю придерживаться старого синтаксиса int x = 0
, но это сводится к личным предпочтениям.
Для типов классов, инициализация скобок и инициализация конструктора старой школы не являются полностью взаимозаменяемыми. Например:
vector<int> v (100); // Creates a 100-element vector
vector<int> v {100}; // Creates a 1-element vector, holding the value 100.
Это связано с тем, что std::vector
имеет конструктор, который явно определяет std::initializer_list
как единственный аргумент. Имейте в виду, что
auto var = {1, 2};
создает std::initializer_list
с var
в качестве своего идентификатора.
Вещь списков инициализаторов заключается в том, что они обеспечивают согласованность, которая является долгожданным изменением от того, что было доступно заранее. Например, если вы хотите инициализировать массив на С++, вы должны использовать:
int arr[] = {1, 2, 3, 4};
Но если вы хотите инициализировать vector<int>
с теми же элементами, вам либо пришлось:
- Сначала инициализируйте вышеуказанный arr, а затем передайте
arr
иarr + 4
- Создайте вектор и push_back() элементы по отдельности или в цикле.
С С++ 11 вы можете просто использовать
vector<int> v = {1, 2, 3, 4}; // Same syntax. Nice! Note that the = is optional
Другим примером, в котором рекомендуется инициализация скобок, является то, что он обеспечивает обходное решение для С++ наиболее неприятного анализа. Из разговора предположим, что у нас есть два класса: origin
и extents
, экземпляры которых могут быть переданы для построения другого объекта типа rectangle
. Следующее утверждение:
rectangle w(origin(), extents());
не позволяет вам создать объект rectangle
, используя origin
и extents
temporaries, потому что этот оператор анализируется как объявление функции. Tsk tsk. Так что обычно вам нужно будет:
origin o;
extents e;
rectangle w(o, e);
С инициализацией скобки вы можете создать их на лету, а
rectangle w {origin(), extents()};
будет работать по назначению, т.е. передается конструктору, который перегружен объектом origin
в качестве первого аргумента, а объект extents
- вторым.
Правило для объектов, используйте фиксацию скобки, если у вас нет причины.