Инициализация уникального указателя в классе

Предположим, у меня есть unique_ptr объект-член, который я хочу инициализировать в классе, см. код ниже. Почему я должен использовать равномерную инициализацию (фигурные скобки)? Второе объявление выдает ошибку, что-то вроде

so.cpp:10:31: error: expected parameter declarator
std::unique_ptr<Foo> upf2(new Foo);
^
so.cpp:10:31: error: expected ')'
so.cpp:10:30: note: to match this '('
std::unique_ptr<Foo> upf2(new Foo);                             ^
2 errors generated.

И я не думаю, что это самая неприятная проблема синтаксического анализа, по крайней мере, я не верю в это.

#include <memory>

class Foo
{

};

class Bar{
std::unique_ptr<Foo> upf1{new Foo}; // works fine
//    std::unique_ptr<Foo> upf2(new Foo); // error here
};

int main()
{
Bar bar;
}

5

Решение

Инициализатор нестатического члена данных (NSDMI) должен использовать скобки или равно-инициализатор. ( expression-list ) форма инициализации не допускается.

Как N2756 объясняет, чтобы позволить NSDMI вести себя более как традиционные списки инициализаторов членов конструктора, имена внутри инициализаторов ищутся в области видимости всего класса. К сожалению, это означает, что использование инициализаторов в скобках сделало бы невозможным определение того, является ли что-то инициализатором или объявлением функции во время синтаксического анализа объявления:

// not real code
struct X {
int i(x);    // initializer
static int x;
};

struct Y {
int i(x);    // function
typedef int x;
};

В документе обсуждались несколько возможных способов исправить этот недостаток, полностью запретив его («все, что может быть объявлением, является объявлением» или «это не тип, если вы не говорите, что это тип»), но ни один из них не очень привлекателен, и Считалось, что потенциальная путаница перевешивает выгоду от разрешения этой формы инициализации.

7

Другие решения

Потому что таковы правила. Инициализаторы в классе должны использовать «фигурные скобки» или «равно»; на самом деле, синтаксический элемент называется скобки или равно-инициализатор.

int equals = 42;                      // OK
std::unique_ptr<Foo> braces{new Foo}; // Also OK

Я не знаю, почему круглые скобки не допускаются; возможно, чтобы избежать возможности инициализации, похожей на объявление функции. Это может раздражать, когда есть разница между прямой и фигурной инициализацией:

std::vector<int> bad(6);                     // ERROR: parentheses not allowed
std::vector<int> good{6};                    // OK but not the same
std::vector<int> ugly = std::vector<int>(6); // OK but ugly
9

По вопросам рекламы [email protected]