Пространства имён
Варианты
Действия

Инициализация по умолчанию

Материал из cppreference.com
< cpp‎ | language
 
 
 
 

Это инициализация выполняется, когда объект создается без инициализатора.

Содержание

[править]Синтаксис

T объект ; (1)
newT (2)

[править]Объяснение

Инициализация по умолчанию выполняется в трёх случаях:

1) когда переменная с автоматической, статической или потоковой длительностью хранения объявлена без инициализатора;
2) когда объект с динамической длительностью хранения создаётся с помощью выражения new без инициализатора;
3) когда базовый класс или нестатический элемент данных не упоминается в списке инициализаторов конструктора и вызывается этот конструктор.

Эффект инициализации по умолчанию:

  • если T является (возможно cv-квалифицированным) не-POD(до C++11) типом класса, конструкторы рассматриваются и подвергаются разрешению перегрузки с пустым списком аргументов. Выбранный конструктор (который является одним из конструкторов по умолчанию) вызывается для предоставления начального значения для нового объекта;
  • если T является типом массива, каждый элемент массива инициализируется по умолчанию;
  • иначе инициализация не производится (смотрите примечание).

[править]Инициализация по умолчанию константного объекта

Если программа требует инициализации по умолчанию объекта const-квалифицированного типа T, T должен быть константно по умолчанию создаваемым типом класса или его массивом.

Тип класса T является константно по умолчанию создаваемым, если инициализация по умолчанию T вызовет предоставленный пользователем конструктор класса T(не унаследованный от базового класса)(начиная с C++11) или если

Только (возможно, cv-квалифицированные) не-POD типы классов (или их массивы) с автоматической длительностью хранения считались инициализированными по умолчанию, когда не используется инициализатор. Скалярные и POD типы с динамической длительностью хранения считались неинициализированными (начиная с C++11, эта ситуация была переклассифицирована как форма инициализации по умолчанию).

(до C++11)
  • каждый прямой нестатический элемент данных M из T имеет тип класса X (или его массив), где X является константно по умолчанию создаваемым, и
  • T не содержит прямых вариантных элементов, и
(до C++11)
  • каждый прямой невариантный нестатический элемент данных M из T имеет инициализатор элемента по умолчанию или, если M имеет тип класса X (или его массив), тогда X является константно по умолчанию создаваемым,
  • если T является объединением хотя бы с одним нестатическим элементом данных, ровно один вариантный элемент имеет инициализатор элемента по умолчанию,
  • если T не является объединением, для каждого анонимного элемента объединения по крайней мере с одним нестатическим элементом данных (если есть), ровно один нестатический элемент данных имеет инициализатор элемента по умолчанию, и
(начиная с 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, кэшированного в
регистре, было неопределённым поведением
сделано чётко определённым

[править]Смотрите также

close