After coming back to C++ following about 18 years away, I ran into the five commonly discussed initialization forms and found the distinctions surprisingly confusing:
int a; // default-initialization
int b = 5; // copy-initialization
int c(6); // direct-initialization
int d{7}; // direct-list-initialization
int e{}; // value-initialization
Why are there so many forms, and what are the practical differences between them? Is brace initialization really preferred today? Also, is there anything wrong with declaring a variable first and assigning it afterward, like this?
int x;
x = 10;
3 Answers
The repeated initialization section looks like an accidental duplicate, which makes the explanation seem more complicated than it is. The different syntaxes mostly exist because C++ evolved over decades and had to preserve compatibility while adding constructors, objects, containers, and safer initialization rules.
For simple values, `int b = 5`, `int c(5)`, and `int d{5}` usually produce the same result. Brace initialization is commonly preferred for new code because it gives a more consistent syntax and rejects narrowing conversions. For example, `int x{3.14};` is an error, while `int x = 3.14;` is allowed and silently converts the value.
Declaring and assigning later is still valid C++, but it is not initialization. Between the declaration and the assignment, the variable may contain an indeterminate value, so using it during that period is unsafe. It also cannot be used for things such as a `const` variable, which must be initialized when it is declared.
If you already know the value, initializing immediately is generally clearer: `int x{10};`. Separate assignment still makes sense when the value is only available later or must be calculated conditionally.
The three nonempty forms have different historical and language-level rules. `=` is the older copy-initialization syntax inherited from C-style usage, parentheses are direct initialization and interact naturally with constructors, and braces were added later as a more uniform initialization syntax for built-in types and class types.
Braces are not universally mandatory, though. They can sometimes select a different constructor, especially one taking an initializer list, so experienced C++ programmers still choose between parentheses and braces based on the type and desired behavior. For ordinary integer initialization, `int value{5};` is a solid default.

The main safety difference is easy to see with conversions: `int x; x = 3.14;` is legal and truncates the value, while `int x{3.14};` is rejected. That compile-time check is one reason braces are useful.