Инициализация по умолчанию
Это инициализация выполняется, когда объект создается без инициализатора.
Содержание |
[править]Синтаксис
T объект ; | (1) | ||||||||
new T | (2) | ||||||||
[править]Объяснение
Инициализация по умолчанию выполняется в трёх случаях:
Эффект инициализации по умолчанию:
- если
T
является (возможно cv-квалифицированным) не-POD(до C++11) типом класса, конструкторы рассматриваются и подвергаются разрешению перегрузки с пустым списком аргументов. Выбранный конструктор (который является одним из конструкторов по умолчанию) вызывается для предоставления начального значения для нового объекта; - если
T
является типом массива, каждый элемент массива инициализируется по умолчанию; - иначе инициализация не производится (смотрите примечание).
Только (возможно, cv-квалифицированные) не-POD типы классов (или их массивы) с автоматической длительностью хранения считались инициализированными по умолчанию, когда не используется инициализатор. Скалярные и POD типы с динамической длительностью хранения считались неинициализированными (начиная с C++11, эта ситуация была переклассифицирована как форма инициализации по умолчанию). | (до C++11) |
| (до C++11) |
| (начиная с C++11) |
каждый потенциально конструируемый базовый класс T
является константно по умолчанию создаваемым.
[править]Чтение из неопределённого байта
Использование неопределённого значения, полученного путём инициализации по умолчанию переменной любого типа, не относящейся к классу, является неопределённым поведением (в частности, это может быть представлением ловушкой), за исключением следующих случаев:
- если неопределённое значение типа unsignedcharили std::byte(начиная с C++17) присвоено другой (возможно, cv-квалифицированной) переменной типа unsignedcharили std::byte(начиная с C++17) (значение переменной становится неопределённым, но поведение нет);
- если неопределённое значение типа unsignedcharили std::byte(начиная с C++17) используется для инициализации другой (возможно, cv-квалифицированной) переменной типа unsignedcharили std::byte(начиная с C++17);
- если неопределённое значение типа unsignedcharили std::byte(начиная с C++17) является результатом
- второго или третьего операнда условного выражения,
- правым операндом оператора запятая,
- операнда приведения или преобразования в (возможно, cv-квалифицированный) unsignedcharили std::byte(начиная с C++17),
- выражения с отброшенным значением.
int f(bool b){int x;// OK: значение x неопределеноint y = x;// неопределённое поведениеunsignedchar c;// OK: значение c неопределеноunsignedchar d = c;// OK: значение d неопределеноint e = d;// неопределённое поведениеreturn b ? d :0;// поведение неопределено, если b истинно}
[править]Примечание
Инициализация по умолчанию переменных, не относящихся к классу, с автоматической и динамической длительностью хранения, создаёт объекты с неопределёнными значениями (статические и локальные объекты потока получают инициализацию нулём).
Ссылочные и константные скалярные объекты не могут быть инициализированы по умолчанию.
[править]Пример
#include <string> struct T1 {int mem;}; struct T2 {int mem; T2(){}// "mem" отсутствует в списке инициализаторов}; int n;// статическая неклассовая переменная, выполняется двухэтапная инициализация:// 1) нулевая инициализация инициализирует n нулём// 2) инициализация по умолчанию ничего не делает, оставляя n равным нулю int main(){int n;// не класс, значение неопределеноstd::string s;// класс, вызывает конструктор по умолчанию, значение ""// (пустая строка)std::string a[2];// массив, инициализирует элементы по умолчанию, значение// равно {"", ""}// int& r; // ошибка: ссылка// const int n; // ошибка: константа не класс// const T1 t1; // ошибка: константный класс с неявным конструктором по умолчанию T1 t1;// класс, вызывает неявный конструктор по умолчаниюconst T2 t2;// константный класс, вызывает предоставленный пользователем// конструктором по умолчанию// t2.mem инициализируется по умолчанию (в неопределённое значение)}
[править]Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
Номер | Применён | Поведение в стандарте | Корректное поведение |
---|---|---|---|
CWG 178 | C++98 | нет инициализации значением; пустой инициализатор вызывает инициализацию по умолчанию (хотя new T() также выполняет инициализацию нулём) | пустой инициализатор вызывает инициализацию значением |
CWG 253 | C++98 | инициализация константного объекта по умолчанию не могла вызвать неявно объявленный конструктор по умолчанию | разрешено, если все подобъекты инициализированы |
CWG 616 | C++98 | преобразование lvalue в rvalue любого неинициализированного объекта всегда было неопределённым поведением | неопределённый unsignedchar разрешён |
CWG 1787 | C++98 | чтение из неопределённого unsignedchar, кэшированного в регистре, было неопределённым поведением | сделано чётко определённым |