Zero-initialization
Устанавливает начальное значение объекта равным нулю.
Содержание |
Синтаксис
Обратите внимание, что это не синтаксис для zero-initialization, который не имеет специального синтаксиса в языке. Это примеры других типов инициализации, которые могут выполнять zero-initialization.
static
T
object
;
|
(1) | ||||||||
T
()
;
T
t
T
|
(2) | ||||||||
CharT
array
[
n
]
=
"
short-sequence
";
|
(3) | ||||||||
Объяснение
Обнуляющая инициализация выполняется в следующих ситуациях:
Эффекты от инициализации нулями:
-
Если
Tявляется скалярным типом , объект инициализируется значением, полученным путём явного преобразования целочисленного литерала 0 (ноль) к типуT. -
Если
Tявляется типом класса (не объединением):
-
- все биты заполнения инициализируются нулевыми битами,
- каждый нестатический член данных инициализируется нулями,
- каждый невиртуальный базовый класс подобъект инициализируется нулями, и
- если объект не является подобъектом базового класса, каждый подобъект виртуального базового класса инициализируется нулями.
-
Если
Tявляется типом объединения:
-
- все биты заполнения инициализируются нулевыми битами, и
- первый нестатический именованный элемент данных объекта инициализируется нулями.
-
Если
Tявляется типом массива, каждый элемент инициализируется нулями. -
Если
Tявляется ссылочным типом, ничего не выполняется.
Примечания
Как описано в разделе инициализация нелокальных переменных , статические и thread-local (since C++11) переменные, которые не являются константно-инициализированными, проходят zero-инициализацию до выполнения любой другой инициализации. Если определение неклассовой нелокальной переменной не имеет инициализатора, то default-инициализация не выполняет никаких действий, оставляя результат предыдущего zero-инициализации неизменным.
Обнуленный указатель является нулевым указателем своего типа, даже если значение нулевого указателя не является целочисленным нулем.
Пример
#include <iostream> #include <string> struct A { int a, b, c; }; double f[3]; // инициализированы нулями до трёх 0.0 int* p; // инициализирован нулём как нулевой указатель // (даже если значение не является целочисленным 0) std::string s; // инициализирован неопределённым значением, затем // инициализирован по умолчанию как "" конструктором std::string по умолчанию int main(int argc, char*[]) { delete p; // безопасно удалить нулевой указатель static int n = argc; // инициализирован нулём, затем копирующая инициализация значением argc std::cout << "n = " << n << '\n'; A a = A(); // эффект такой же как: A a{}; или A a = {}; std::cout << "a = {" << a.a << ' ' << a.b << ' ' << a.c << "}\n"; }
Возможный вывод:
n = 1
a = {0 0 0}
Отчеты о дефектах
Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены задним числом к ранее опубликованным стандартам C++.
| DR | Применяется к | Поведение в опубликованной версии | Корректное поведение |
|---|---|---|---|
| CWG 277 | C++98 |
указатели могли инициализироваться неконстантным
выражением со значением 0, которое не является константой нулевого указателя |
должна быть инициализация целочисленным
константным выражением со значением 0 |
| CWG 694 | C++98 | обнуляющая инициализация для типов классов игнорировала заполнение | заполнение инициализируется нулевыми битами |
| CWG 903 | C++98 |
обнуляющая инициализация для скалярных типов устанавливала начальное значение в значение,
преобразованное из целочисленного константного выражения со значением 0 |
объект инициализируется значением,
преобразованным из целочисленного литерала 0 |
| CWG 2026 | C++98 |
обнуляющая инициализация была определена как всегда
происходящая первой, даже до константной инициализации |
обнуляющая инициализация не выполняется, если
применяется константная инициализация |
| CWG 2196 | C++98 | обнуляющая инициализация для типов классов игнорировала подобъекты базовых классов | они также обнуляются |
| CWG 2253 | C++98 |
было неясно, применяется ли обнуляющая инициализация
к безымянным битовым полям |
применяется (все биты заполнения
инициализируются нулевыми битами) |