MyClass a1 {a}; // clearer and less error-prone than the other three
MyClass a2 = {a};
MyClass a3 = a;
MyClass a4(a);
Почему?
Я не смог найти ответ на SO, поэтому позвольте мне ответить на мой собственный вопрос.
MyClass a1 {a}; // clearer and less error-prone than the other three
MyClass a2 = {a};
MyClass a3 = a;
MyClass a4(a);
Почему?
Я не смог найти ответ на SO, поэтому позвольте мне ответить на мой собственный вопрос.
auto
?std::map<std::string, std::vector<std::string>>::const_iterator
хотел бы поговорить с вами.using MyContainer = std::map<std::string, std::vector<std::string>>;
это даже лучше (особенно если вы можете создать шаблон!)Ответы:
В основном, копирование и вставка из Бьярна Страуструпа "Язык программирования C ++, 4-е издание" :
Инициализация списка не позволяет сужаться (§iso.8.5.4). Это:
Пример:
Только ситуация , когда = предпочтительнее , чем {}, когда с помощью
auto
ключевого слова , чтобы получить тип , определяемый инициализатором.Пример:
Вывод
Предпочитайте {} инициализацию альтернативам, если у вас нет веских причин не делать этого.
источник
()
может быть проанализировано как объявление функции. Это сбивает с толку и противоречиво, что вы можете сказать,T t(x,y,z);
но нетT t()
. И иногда, вы увереныx
, вы даже не можете сказатьT t(x);
.std::initializer_list
. RedXIII упоминает эту проблему (и просто отмахивается от нее), тогда как вы полностью игнорируете ее.A(5,4)
иA{5,4}
может вызывать совершенно разные функции, и это важно знать. Это может даже привести к вызовам, которые кажутся неинтуитивными. Сказать, что вы предпочитаете{}
по умолчанию, приведет к тому, что люди не поймут, что происходит. Это не твоя вина, хотя. Я лично считаю, что это крайне плохо продуманная функция.auto var{ 5 }
и оно будет выведено какint
не более, чемstd::initializer_list<int>
.Уже есть отличные ответы о преимуществах использования инициализации списка, однако мое личное правило - НЕ использовать фигурные скобки всякий раз, когда это возможно, а вместо этого ставить его в зависимость от концептуального значения:
Во-первых, таким образом, я всегда уверен, что объект инициализируется независимо от того, является ли он, например, «реальным» классом с конструктором по умолчанию, который будет вызван в любом случае, или встроенным / POD-типом. Во-вторых, это - в большинстве случаев - соответствует первому правилу, поскольку инициализированный объект по умолчанию часто представляет собой «пустой» объект.
По моему опыту, этот набор правил может применяться гораздо более последовательно, чем использование фигурных скобок по умолчанию, но при этом необходимо явно помнить все исключения, когда они не могут быть использованы или имеют другое значение, чем «нормальный» синтаксис вызова функции с круглыми скобками. (вызывает другую перегрузку).
Например, он хорошо сочетается со стандартными типами библиотек, такими как
std::vector
:источник
const int &b{}
<- не пытается создать неинициализированную ссылку, а связывает ее с временным целочисленным объектом. Второй пример:struct A { const int &b; A():b{} {} };
<- не пытается создать неинициализированную ссылку (как()
было бы), но связывает ее с временным целочисленным объектом, а затем оставляет его висящим. GCC даже с-Wall
не предупреждает для второго примера.Есть много причин для инициализации использования распорки, но вы должны знать , что конструктор предпочтительнее других конструкторы , исключение составляет по умолчанию, конструктор. Это приводит к проблемам с конструкторами и шаблонами, где конструктор типа может быть либо списком инициализатора, либо простым старым ctor.
initializer_list<>
T
Предполагая, что вы не сталкиваетесь с такими классами, нет особых причин не использовать список инициализаторов.
источник
{ ... }
), если вам не нужнаinitializer_list
семантика (ну, и, возможно, для создания объекта по умолчанию).std::initializer_list
правило существует - оно просто добавляет путаницы и беспорядка в язык. Что не так делать,Foo{{a}}
если вы хотитеstd::initializer_list
конструктор? Это кажется гораздо проще понять, чем иметьstd::initializer_list
приоритет над всеми другими перегрузками.Foo{{a}}
следует некоторой логике для меня гораздо больше, чем то,Foo{a}
что превращается в приоритет списка инициализаторов (ups может подумать пользователь hm ...)std::initializer_list<Foo>
конструктора, но в какой-то момент он будет добавлен вFoo
класс для расширения его интерфейса? Тогда пользователиFoo
класса облажались.initializer_list<>
), которая на самом деле не определяет, кто предпочитает, а затем приводит один хороший случай, когда он НЕ предпочтителен. Что мне не хватает, что ~ 30 других людей (по состоянию на 2016-04-21) сочли полезным?Это только безопаснее, если вы не строите с -не сужением, как, скажем, Google делает в Chromium. Если вы это сделаете, то это менее безопасно. Без этого флага единственные небезопасные случаи будут исправлены C ++ 20.
Примечание: A) фигурные скобки безопаснее, поскольку они не допускают сужения. Б) Вьющиеся скобки менее безопасны, потому что они могут обходить частные или удаленные конструкторы и неявно вызывать явно помеченные конструкторы.
Эти два сочетания означают, что они безопаснее, если внутри находятся примитивные константы, но менее безопасны, если они являются объектами (хотя и исправлены в C ++ 20)
источник