Unified Initialization with {}
Explore the concept of unified initialization in C++11 using {} braces. Understand how this syntax ensures safe and uniform initialization for variables, prevents narrowing conversions, and differs from traditional direct and copy initialization.
We'll cover the following...
The initialization of variables became uniform in C++11. For unified initialization, we need the {} brackets.
{}initialization is always applicable.
Direct initialization
Variables can be declared directly without the assignment operator:
std::string str{"my String"};
int i{2011};
Copy initialization
{} also supports copy initialization with the = operator:
std::string str = {"my String"};
int i = {2011};
The difference is that direct initialization directly calls the constructor of the type, whereas, in copy initialization, the value is created and implicitly converted into the type.
Preventing narrowing
Narrowing, or more precisely narrowing conversion, is an implicit conversion of arithmetic values from one type to another. This can cause a loss of accuracy, which can be extremely dangerous.
The following example shows the issue with the classical way of initializing fundamental types.
The compiler presents a warning, yet the implicit conversions are performed nonetheless, resulting in data loss.
It doesn’t matter whether we use direct initialization or assignment:
The output of the program shows two issues:
-
The
intliteral,999, doesn’t fit into the typechar. -
The
doubleliteral,3.14, doesn’t fit into theinttype.
Such an issue is not possible with {}-initialization.
This given code will give an error.
Now, the ill-formed program is rejected.
The output also depends on the compiler we use. With GCC 6.1 and above, we get an error. Any version below that will only produce a warning.
Don’t believe me? Try it out with the online compiler https://gcc.godbolt.org/.
The clang++ compiler is much more predictable. Therefore, here is a simple tip.
Compile the program in such a way that narrowing is an error.
We can add the flag, -Werror=narrowing, and GCC 4.8 rejects the program instead of producing a warning.
Let’s look at another case:
The expression char c1{97} does not count as narrowing because 97 fits in the char type. The same holds true for char c2 = {97}.
Let’s look at another example to understand {}-initialization better.