Единообразная разница в синтаксисе инициализации


В чем разница между действиями

A a{ A() };

И,

A a( A{} );

Чтобы избежать самого неприятного разбора ? Когда я должен использовать конкретный?

2 10

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"
}