Default member initializer (инициализатор по умолчанию для члена класса) — конструкция C++11, позволяющая объявлять значения по умолчанию прямо при объявлении переменных-членов класса. Эту возможность часто путают с другими способами инициализации данных.
Ранняя C++ не позволяла инициализировать члены прямо при объявлении; значения присваивались только в конструкторе (в теле или списке инициализации). Введение default member initializers (C++11) улучшило читаемость и снизило риск ошибок неопределённой инициализации.
Если поля не проинициализированы явно, они содержат "мусорное" (неопределённое) значение. Присваивание внутри конструктора менее эффективно по сравнению со списком инициализации, а игнорирование default member initializers усложняет расширение классов и создание новых конструкторов.
Использовать default member initializers для простых значений, а для сложных случаев (особенно если необходимо зависимое или нестандартное значение) — списки инициализации конструктора.
Пример кода:
class Widget { int x = 42; // default member initializer std::string name = "default"; // default member initializer public: Widget() = default; // x=42, name="default" Widget(int xx) : x(xx), name("new") {}// x=xx, name="new" };
Ключевые особенности:
Применится ли default member initializer, если член инициализирован внутри тела конструктора, но не в списке инициализации?
Ответ:
Нет. Если не указано в списке инициализации, переменная сначала проинициализируется значением по умолчанию (default member initializer), а потом в теле конструктора произойдёт присваивание, что менее эффективно.
Какой порядок инициализации членов класса с default member initializers при наследовании?
Ответ:
Вначале инициализируются члены базового класса, затем — производного; для каждого члена с default member initializer сначала используется список инициализации конструктора, если он задан, затем — default member initializer, иначе остаётся неинициализированным (для POD). Не происходит "два раза инициализации".
Может ли default member initializer применяться к static-членам класса?
Ответ:
Нет, static-члены не могут быть инициализированы через default member initializer. Их нужно инициализировать вне класса или с помощью inline static в C++17.
Пример:
struct S { static int a = 5; // Ошибка! };
Класс с динамической строкой, которая забыта при инициализации в некоторых конструкторах. Позже при обращении — undefined behavior.
Плюсы:
Минусы:
Все поля имеют default member initializers. Дополнительные конструкторы при необходимости явно инициализируют нужные члены через список инициализации.
Плюсы:
Минусы: