I'm returning to C++ after about 18 years and I'm confused by the different initialization forms. For example:
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 and assigning separately, like this?
int x;
x = 10;
3 Answers
The different forms mostly reflect C++’s history and the need to support both built-in types and class objects. `int b = 5` comes from C-style initialization, parentheses fit constructor calls and direct initialization, and braces were added later as a more uniform syntax for initializing many different kinds of objects. All three forms work for a simple `int`, but they don’t behave identically in every situation.
Brace initialization is commonly preferred because it prevents narrowing conversions. For example, `int x = 3.14;` is accepted, even though the fractional part is discarded, while `int x{3.14};` is rejected. That makes some mistakes visible at compile time. Braces also work consistently with containers and constructors, although they have a few special cases of their own.
There’s nothing inherently wrong with `int x; x = 10;`, but `x` exists without a value in between those two statements. If the assignment is skipped or the variable is read first, a local built-in variable can contain an indeterminate value. Initializing it at the point of declaration avoids that gap and is required for cases such as `const int x`, which must be initialized immediately.
That distinction helps. So the newer forms are mainly about expressing initialization directly, improving type safety, and covering cases that the older syntax cannot handle cleanly.

Separate assignment is still useful when the value cannot be determined until later or when you need to assign a new value repeatedly. The issue isn’t that it is always wrong; it’s that initialization and later assignment are different operations.