Инициализация по умолчанию
Это инициализация, выполняемая при создании объекта без инициализатора.
Синтаксис
Объект T ; | (1) | |
new T | (2) |
Объяснение
Инициализация по умолчанию выполняется в трёх ситуациях:
Эффекты инициализации по умолчанию:
- если
Tявляется (возможно, с квалификатором cv) классом не-POD(до C++11), конструкторы рассматриваются и подвергаются разрешению перегрузки по отношению к пустому списку аргументов. Выбранный конструктор (который является одним из конструкторов по умолчанию) вызывается для задания начального значения для нового объекта; - если
Tявляется типом массива, каждый элемент массива инициализируется по умолчанию; - в противном случае инициализация не выполняется (см. примечания).
| Только (возможно, с квалификатором cv) типы классов не-POD (или массивы таких типов) с автоматической продолжительностью хранения рассматривались как инициализируемые по умолчанию, когда не использовался инициализатор. Скаляры и типы POD с динамической продолжительностью хранения рассматривались как неинициализированные (с C++11 такая ситуация была переквалифицирована как форма инициализации по умолчанию). | (до C++11) |
| (до C++11) |
| (с C++11) |
каждый потенциально созданный базовый класс T допускает инициализацию по умолчанию с квалификатором const.
Чтение из неопределённого байта
Использование неопределённого значения, полученного путём инициализации по умолчанию неклассовой переменной любого типа, является неопределённым поведением (в частности, это может быть представлением ловушки), за исключением следующих случаев:
- если неопределённое значение типа unsigned char или
std::byte(с C++17) присваивается другой переменной типа (возможно, с квалификатором cv) unsigned char илиstd::byte(с C++17) (значение переменной становится неопределённым, но поведение не является неопределённым); - если неопределённое значение типа unsigned char или
std::byte(с C++17) используется для инициализации другой переменной типа (возможно, с квалификатором cv) unsigned char илиstd::byte(с C++17); - если неопределённое значение типа unsigned char или
std::byte(с C++17) является результатом - второго или третьего операнда условного выражения,
- правого операнда оператора запятой,
- операнда приведения типа или преобразования к (возможно, с квалификатором cv) unsigned char или
std::byte(с C++17), - выражения с отбрасываемым значением.
int f(bool b)
{
int x; // OK: the value of x is indeterminate
int y = x; // undefined behavior
unsigned char c; // OK: the value of c is indeterminate
unsigned char d = c; // OK: the value of d is indeterminate
int e = d; // undefined behavior
return b ? d : 0; // undefined behavior if b is true
}Примечания
Инициализация по умолчанию неклассовых переменных с автоматической и динамической продолжительностью хранения производит объекты с неопределёнными значениями (статические и локальные по потоку объекты получают нулевую инициализацию).
Ссылки и скалярные объекты const не могут быть инициализированы по умолчанию.
| Макрос проверки функций | Значение | Стандарт | Функция |
|---|---|---|---|
__cpp_constexpr | 201907L | (C++20) | Тривиальная инициализация по умолчанию и объявление asm в constexpr функциях |
Пример
#include <string>
struct T1 { int mem; };
struct T2
{
int mem;
T2() {} // "mem" is not in the initializer list
};
int n; // static non-class, a two-phase initialization is done:
// 1) zero-initialization initializes n to zero
// 2) default-initialization does nothing, leaving n being zero
int main()
{
[[maybe_unused]]
int n; // non-class, the value is indeterminate
std::string s; // class, calls default ctor, the value is "" (empty string)
std::string a[2]; // array, default-initializes the elements, the value is {"", ""}
// int& r; // error: a reference
// const int n; // error: a const non-class
// const T1 t1; // error: const class with implicit default ctor
[[maybe_unused]]
T1 t1; // class, calls implicit default ctor
const T2 t2; // const class, calls the user-provided default ctor
// t2.mem is default-initialized (to indeterminate value)
}Отчёты об ошибках
Следующие отчёты об ошибках, меняющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.
| Отчёт об ошибке | Применяется к | Поведение при публикации | Правильное поведение |
|---|---|---|---|
| CWG 178 | C++98 | не было инициализации значением; пустой инициализатор вызывал инициализацию по умолчанию (хотя new T() также выполняет нулевую инициализацию) | пустой инициализатор вызывает инициализацию значением |
| CWG 253 | C++98 | инициализация по умолчанию объекта const не могла вызвать неявно объявленный конструктор по умолчанию | разрешено, если все подобъекты инициализированы |
| CWG 616 | C++98 | преобразование lvalue в rvalue любого неинициализированного объекта всегда было UB | неопределённое unsigned char разрешено |
| CWG 1787 | C++98 | чтение из неопределённого unsigned char кэшированного в регистре было UB | сделано хорошо определённым |
См. также
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/language/default_initialization