Почему мы не можем инициализировать членов класса при их объявлении?

Интересно, есть ли причина, по которой мы не можем инициализировать членов при их объявлении.

class Foo
{
    int Bar = 42; // this is invalid
};

Как эквивалент использования списков инициализации конструктора.

class Foo
{
    int Bar;
public:
    Foo() : Bar(42) {}
}

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

Есть ли официальные разъяснения по этому поводу?

Ответы

Ответ 1

Инициализация нестатических членов не может быть выполнена так, как это было до С++ 11. Если вы компилируете компилятор С++ 11, он должен с радостью принять код, который вы указали.

Я предполагаю, что причина не позволять ему в первую очередь состоит в том, что объявление члена данных не является определением. Объекта не вводится. Если у вас есть элемент данных, такой как int x;, объект int не создается, пока вы фактически не создадите объект типа класса. Следовательно, инициализатор этого элемента будет вводить в заблуждение. Только во время построения значение может быть присвоено члену, что и есть для списков инициализации членов.

Были также некоторые технические проблемы, которые можно было бы сгладить, прежде чем можно было бы добавить инициализацию нестатического члена. Рассмотрим следующие примеры:

struct S {
    int i(x);
    // ...
    static int x;
};

struct T {
    int i(x);
    // ...
    typedef int x;
};

Когда эти структуры разбираются во время разбора элемента i, он неоднозначен, является ли это объявлением члена данных (как в S) или объявлением функции-члена (как в T),.

С добавленной функциональностью это не проблема, потому что вы не можете инициализировать элемент с помощью этого синтаксиса скобок. Вы должны использовать логический или равный инициализатор, например:

int i = x;
int i{x};

Это могут быть только члены данных, поэтому у нас больше нет проблем.

См. предложение N2628 для более тщательного изучения проблем, которые необходимо учитывать при разработке инициализаторов нестатического элемента.

Ответ 2

Основная причина заключается в том, что инициализация применяется к объекту или экземпляр, а в объявлении в классе нет объект или экземпляр; у вас этого нет, пока вы не начнете конструкционный.

В этом отношении произошла определенная эволюция. Уже на в самом конце стандартизации С++ 98, комитет добавил возможность сделать это для статических константных членов интеграла типа --- главным образом потому, что они могут использоваться в контекстах, где компилятор должен иметь возможность видеть инициализацию. В С++ 11 язык был расширен, чтобы можно было указать инициализатор в декларация, но это всего лишь стенография. инициализация по-прежнему выполняется в верхней части конструктора.

Ответ 3

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