Единообразная разница в синтаксисе инициализации
В чем разница между действиями
A a{ A() };
И,
A a( A{} );
Чтобы избежать самого неприятного разбора ? Когда я должен использовать конкретный?
2 ответа:
Эти два синтаксиса эквивалентны в большинстве ситуаций, и какой из них выбрать-в основном дело вкуса. Если вы занимаетесь единообразной инициализацией, я бы предложил сделать:
A a{ A{} };
В противном случае для устранения двусмысленности можно использовать только круглые скобки:
Обратите внимание, что есть одна ситуация (очень маловероятная, я должен сказать), где две формы, показанные в вашем вопросе, не эквивалентны. Если ваш классA a((A())); // This can't be parsed as a function declaration
A
имеет конструктор, который принимаетinitializer_list<A>
, этот конструктор будет предпочтительнее, чем конструктор копирования при использовании фигурных скобок:#include <initializer_list> #include <iostream> struct A { A() { } A(std::initializer_list<A> l) { std::cout << "init-list" << std::endl; } A(A const& a) { std::cout << "copy-ctor" << std::endl; } }; int main() { A a(A{}); // Prints "copy-ctor" (or nothing, if copy elision is performed) A b{A()}; // Prints "init-list" }
Приведенная выше разница проявляется в следующем: живой пример.
В большинстве случаев они эквивалентны, но
A a{ A() };
предпочтет конструкторstd::initializer_list
, если он присутствует, в то время какA a( A{} );
предпочтет конструктор перемещения/копирования.Когда конструкция завершается вызовом конструктора перемещения / копирования, построение нового объекта может быть отменено, но это невозможно для конструктора
Ни один синтаксис никогда не будет проанализирован как объявление функции, поэтому оба избегают самого неприятного синтаксического анализа.std::initializer_list
.#include <iostream> #include <initializer_list> struct A { A() { std::cout << "A()\n"; } A(A&&) { std::cout << "A(A&&)\n"; } A(std::initializer_list<A>) { std::cout << "A(std::initializer_list<A>)\n"; } }; int main() { {A a{ A() };} // Prints "A()\n" "A(std::initializer_list<A>)\n" {A a( A{} );} // Prints "A()\n" and *possibly* // (depending on copy elision) "A(A&&)\n" }