До C ++ 11 мы могли выполнять инициализацию внутри класса только для статических констант целочисленного или перечислимого типа. Страуструп обсуждает это в своем FAQ по C ++ , приводя следующий пример:
class Y {
const int c3 = 7; // error: not static
static int c4 = 7; // error: not const
static const float c5 = 7; // error: not integral
};
И следующие рассуждения:
Так почему же существуют эти неудобные ограничения? Класс обычно объявляется в файле заголовка, а файл заголовка обычно включается во многие единицы перевода. Однако, чтобы избежать сложных правил компоновщика, C ++ требует, чтобы каждый объект имел уникальное определение. Это правило было бы нарушено, если бы C ++ допускал определение внутри класса сущностей, которые необходимо было хранить в памяти как объекты.
Однако C ++ 11 ослабляет эти ограничения, позволяя инициализировать нестатические члены в классе (§12.6.2 / 8):
В конструкторе без делегирования, если данный нестатический член данных или базовый класс не обозначен идентификатором mem-initializer-id (включая случай, когда нет mem-initializer-list, потому что конструктор не имеет инициализатора ctor ) и объект не является виртуальным базовым классом абстрактного класса (10.4), тогда
- если объект является нестатическим элементом данных, который имеет инициализатор в форме скобки или равенства , объект инициализируется, как указано в 8.5;
- в противном случае, если объект является вариантным членом (9.5), инициализация не выполняется;
- в противном случае объект инициализируется по умолчанию (8.5).
Раздел 9.4.2 также позволяет инициализировать в классе неконстантные статические члены, если они помечены constexpr
спецификатором.
Так что же случилось с причинами ограничений, которые были у нас в C ++ 03? Мы просто принимаем «сложные правила компоновщика» или изменили что-то еще, что упрощает реализацию?