Difference between revisions of "cpp/language/zero initialization"
m (Added missing C++11 inline marks for thread-local variables.) |
(Added CWG issue #277 DR.) |
||
Line 8: | Line 8: | ||
{{sdsc begin}} | {{sdsc begin}} | ||
− | {{sdsc | num=1 | {{ttb|static}} {{spar|T}} {{spar| object}} {{ttb|;}}}} | + | {{sdsc|num=1|{{ttb|static}} {{spar|T}} {{spar| object}} {{ttb|;}}}} |
− | {{sdsc | num=2 |notes=<br><br>{{mark since c++11}}|{{spar|T}} {{ttb|()}} {{ttb|;}} | + | {{sdsc|num=2|notes=<br><br>{{mark since c++11}}|{{spar|T}} {{ttb|()}} {{ttb|;}} |
{{spar|T}} {{spar|t}} {{ttb|{{=}}}} {{ttb|{}<nowiki/>}} {{ttb|;}} <br> | {{spar|T}} {{spar|t}} {{ttb|{{=}}}} {{ttb|{}<nowiki/>}} {{ttb|;}} <br> | ||
{{spar|T}} {{ttb|{}<nowiki/>}} {{ttb|;}} | {{spar|T}} {{ttb|{}<nowiki/>}} {{ttb|;}} | ||
}} | }} | ||
− | {{sdsc | num=3 | {{spar|CharT}} {{spar|array}} {{ttb|[}} {{spar|n}} {{ttb|]}} {{ttb|{{=}}}} {{ttb|"";}}}} | + | {{sdsc|num=3|{{spar|CharT}} {{spar|array}} {{ttb|[}} {{spar|n}} {{ttb|]}} {{ttb|{{=}}}} {{ttb|"";}}}} |
{{sdsc end}} | {{sdsc end}} | ||
Line 21: | Line 21: | ||
@1@ For every named variable with static{{rev inl|since=c++11| or thread-local}} {{rlp|storage duration}} that is not subject to {{rlp|constant initialization}}, before any other initialization. | @1@ For every named variable with static{{rev inl|since=c++11| or thread-local}} {{rlp|storage duration}} that is not subject to {{rlp|constant initialization}}, before any other initialization. | ||
@2@ As part of {{rlp|value initialization|value-initialization}} sequence for non-class types and for members of value-initialized class types that have no constructors, including value initialization of elements of {{rlp|aggregate initialization|aggregates}} for which no initializers are provided. | @2@ As part of {{rlp|value initialization|value-initialization}} sequence for non-class types and for members of value-initialized class types that have no constructors, including value initialization of elements of {{rlp|aggregate initialization|aggregates}} for which no initializers are provided. | ||
− | @3@ When an array of any {{rlp|types# | + | @3@ When an array of any {{rlp|types#Character types|character type}} is {{rlp|aggregate initialization#Character arrays|initialized with a string literal}} that is too short, the remainder of the array is zero-initialized. |
The effects of zero initialization are: | The effects of zero initialization are: | ||
Line 36: | Line 36: | ||
===Notes=== | ===Notes=== | ||
− | As described in {{rlp|initialization#Non- | + | As described in {{rlp|initialization#Non-local variables|non-local initialization}}, static{{rev inl|since=c++11| and thread-local}} variables that aren't constant-initialized are zero-initialized before any other initialization takes place. If the definition of a non-class non-local variable has no initializer, then default initialization does nothing, leaving the result of the earlier zero-initialization unmodified. |
A zero-initialized pointer is the null pointer value of its type, even if the value of the null pointer is not integral zero. | A zero-initialized pointer is the null pointer value of its type, even if the value of the null pointer is not integral zero. | ||
Line 48: | Line 48: | ||
#include <iostream> | #include <iostream> | ||
− | struct A { | + | struct A |
− | int a,b,c; | + | { |
+ | int a, b, c; | ||
}; | }; | ||
− | double f[3]; // zero-initialized to three 0.0's | + | double f[3]; // zero-initialized to three 0.0's |
− | int* p; // zero-initialized to null pointer value (even if the value is not integral 0) | + | |
− | std::string s; // zero-initialized to indeterminate value | + | int* p; // zero-initialized to null pointer value |
− | // | + | // (even if the value is not integral 0) |
+ | |||
+ | std::string s; // zero-initialized to indeterminate value, then | ||
+ | // default-initialized to "" by the std::string default constructor | ||
+ | |||
int main(int argc, char*[]) | int main(int argc, char*[]) | ||
{ | { | ||
delete p; // safe to delete a null pointer | delete p; // safe to delete a null pointer | ||
+ | |||
static int n = argc; // zero-initialized to 0 then copy-initialized to argc | static int n = argc; // zero-initialized to 0 then copy-initialized to argc | ||
std::cout << "n = " << n << '\n'; | std::cout << "n = " << n << '\n'; | ||
+ | |||
A a = A(); // the effect is same as: A a{}; or A a = {}; | A a = A(); // the effect is same as: A a{}; or A a = {}; | ||
std::cout << "a = {" << a.a << ' ' << a.b << ' ' << a.c << "}\n"; | std::cout << "a = {" << a.a << ' ' << a.b << ' ' << a.c << "}\n"; | ||
} | } | ||
− | | p=true <!-- argc --> | + | |p=true <!-- argc --> |
− | | output= | + | |output= |
n = 1 | n = 1 | ||
a = {0 0 0} | a = {0 0 0} | ||
Line 72: | Line 79: | ||
===Defect reports=== | ===Defect reports=== | ||
{{dr list begin}} | {{dr list begin}} | ||
− | {{dr list item|wg=cwg|dr=2026|std=C++98|before=zero | + | {{dr list item|wg=cwg|dr=277|std=C++98|before=pointers might be initialized with a non-constant<br>expression of value 0, which is not a null pointer constant|after=must initialize with an integral<br>constant expression of value 0}} |
+ | {{dr list item|wg=cwg|dr=2026|std=C++98|before=zero initialization was specified to always<br>occur first, even before constant initialization|after=no zero initialization if<br>constant initialization applies}} | ||
{{dr list end}} | {{dr list end}} | ||
===See also=== | ===See also=== | ||
− | * {{rlp | constructor}} | + | * {{rlp|constructor}} |
− | * {{rlp | copy assignment}} | + | * {{rlp|copy assignment}} |
− | * {{rlp | default constructor}} | + | * {{rlp|default constructor}} |
− | * {{rlp | initialization}} | + | * {{rlp|initialization}} |
− | ** {{rlp | aggregate initialization}} | + | ** {{rlp|aggregate initialization}} |
− | ** {{rlp | constant initialization}} | + | ** {{rlp|constant initialization}} |
− | ** {{rlp | copy initialization}} | + | ** {{rlp|copy initialization}} |
− | ** {{rlp | default initialization}} | + | ** {{rlp|default initialization}} |
− | ** {{rlp | direct initialization}} | + | ** {{rlp|direct initialization}} |
− | ** {{rlp | list initialization}} | + | ** {{rlp|list initialization}} |
− | ** {{rlp | value initialization}} | + | ** {{rlp|value initialization}} |
− | * {{rlp | move assignment}} | + | * {{rlp|move assignment}} |
− | * {{rlp | new}} | + | * {{rlp|new}} |
{{langlinks|de|es|fr|it|ja|pt|ru|zh}} | {{langlinks|de|es|fr|it|ja|pt|ru|zh}} |
Revision as of 23:35, 24 January 2022
Sets the initial value of an object to zero.
Contents |
Syntax
Note that this is not the syntax for zero initialization, which does not have a dedicated syntax in the language. These are examples of other types of initializations, which might perform zero initialization.
static T object ;
|
(1) | ||||||||
T () ;
T t |
(2) | (since C++11) | |||||||
CharT array [ n ] = "";
|
(3) | ||||||||
Explanation
Zero initialization is performed in the following situations:
The effects of zero initialization are:
- If
T
is a scalar type, the object's initial value is the integral constant zero explicitly converted toT
.
- If
T
is an non-union class type, all base classes and non-static data members are zero-initialized, and all padding is initialized to zero bits. The constructors, if any, are ignored.
- If
T
is a union type, the first non-static named data member is zero-initialized and all padding is initialized to zero bits.
- If
T
is array type, each element is zero-initialized.
- If
T
is reference type, nothing is done.
Notes
As described in non-local initialization, static and thread-local(since C++11) variables that aren't constant-initialized are zero-initialized before any other initialization takes place. If the definition of a non-class non-local variable has no initializer, then default initialization does nothing, leaving the result of the earlier zero-initialization unmodified.
A zero-initialized pointer is the null pointer value of its type, even if the value of the null pointer is not integral zero.
Example
#include <string> #include <iostream> struct A { int a, b, c; }; double f[3]; // zero-initialized to three 0.0's int* p; // zero-initialized to null pointer value // (even if the value is not integral 0) std::string s; // zero-initialized to indeterminate value, then // default-initialized to "" by the std::string default constructor int main(int argc, char*[]) { delete p; // safe to delete a null pointer static int n = argc; // zero-initialized to 0 then copy-initialized to argc std::cout << "n = " << n << '\n'; A a = A(); // the effect is same as: A a{}; or A a = {}; std::cout << "a = {" << a.a << ' ' << a.b << ' ' << a.c << "}\n"; }
Possible output:
n = 1 a = {0 0 0}
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 277 | C++98 | pointers might be initialized with a non-constant expression of value 0, which is not a null pointer constant |
must initialize with an integral constant expression of value 0 |
CWG 2026 | C++98 | zero initialization was specified to always occur first, even before constant initialization |
no zero initialization if constant initialization applies |