CPP Initialization - rFronteddu/general_wiki GitHub Wiki
Initialization is not straight-forward, here are 5 common forms of initialization:
int a; // default-initialization (no initializer)
// traditional initialization forms:
int b = 5; // copy-initialization
int c ( 6 ); // direct-initialization
// modern initialization
int d { 7 }; // direct-list-initialization
int e {}; // value-initialization
As of C++17, copy-initialization, direct-initialization, and direct-list-initialization behave identically in most cases.
Default Initialization
When no initializer is provided, this is called default-initialization. Often default-initialization performs no initialization, and leaves the variable with an indeterminate value (called a “garbage value”).
Copy-initialization
When an initial value is provided after an equals sign, this is called copy-initialization. This form of initialization was inherited from the C language.
Copy-initialization had fallen out of favor in modern C++ due to being less efficient than other forms of initialization for some complex types. However, C++17 remedied the bulk of these issues, and copy-initialization is now finding new advocates.
Copy-initialization is also used whenever values are implicitly copied, such as when passing arguments to a function by value, returning from a function by value, or catching exceptions by value.
Direct Initialization
When an initial value is provided inside parenthesis, this is called direct-initialization.
Just like copy-initialization, direct-initialization had fallen out of favor in modern C++, largely due to being superseded by direct-list-initialization. However, direct-list-initialization has a few quirks of its own, and so direct-initialization is once again finding use in certain cases.
Direct-initialization is also used when values are explicitly cast to another type (e.g. via static_cast).
List Initialization
The modern way to initialize objects in C++ is to use a form of initialization that makes use of curly braces. This is called list-initialization (or uniform initialization or brace initialization). It comes in two forms:
int width { 5 }; // direct-list-initialization
int height = { 6 }; // copy-list-initialization, rarely used
Prior to C++11, some types of initialization required using copy-initialization, and other types of initialization required using direct-initialization. Copy-initialization can be hard to differentiate from copy-assignment (because both use an =). And direct-initialization can be difficult to differentiate from function-related operations (because both use parentheses).
List-initialization was introduced to provide a initialization syntax that works in almost all cases, behaves consistently, and has an unambiguous syntax that makes it easy to tell where we’re initializing an object. When we see curly braces, we know we’re list-initializing an object.
Additionally, list-initialization also provides a way to initialize objects with a list of values rather than a single value (which is why it is called “list-initialization”).
List initialization disallows narrowing conversions
One of the primary benefits of list-initialization for new C++ programmers is that “narrowing conversions” are disallowed. This means that if you try to list-initialize a variable using a value that the variable can not safely hold, the compiler is required to produce a diagnostic (compilation error or warning) to notify you. Copy-initialization and direct-initialization silently narrows types.
Value initialization and zero initialization
When a variable is initialized using an empty set of braces, a special form of list-initialization called value-initialization takes place. In most cases, value-initialization will implicitly initialize the variable to zero (or whatever value is closest to zero for a given type). In cases where zeroing occurs, this is called zero-initialization.