Spec-Zone.ru › C++

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

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

Синтаксис

Объект T ; (1)
new T (2)

Объяснение

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

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

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

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

Инициализация по умолчанию объекта const

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

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

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

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

См. также

  • преобразующий конструктор
  • конструктор по умолчанию
  • explicit
  • инициализация
    • инициализация агрегатов
    • инициализация констант
    • инициализация копированием
    • прямая инициализация
    • инициализация списком
    • инициализация ссылок
    • инициализация значением
    • нулевая инициализация
  • new

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/language/default_initialization

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API