MyClass a1 {a}; // clearer and less error-prone than the other three MyClass a2 = {a}; MyClass a3 = a; MyClass a4(a);
Why?
In programming, curly braces (the { and } characters) are used in a variety of ways. In C/C++, they are used to signify the start and end of a series of statements. In the following expression, everything between the { and } are executed if the variable mouseDOWNinText is true.
Different programming languages have various ways to delineate the start and end points of a programming structure, such as a loop, method or conditional statement. For example, Java and C++ are often referred to as curly brace languages because curly braces are used to define the start and end of a code block.
In languages like C curly braces ( {} ) are used to create program blocks used in flow control. In Python, curly braces are used to define a data structure called a dictionary (a key/value mapping), while white space indentation is used to define program blocks.
The code above shows how curly braces can be used to declare various types of variables and assign values to them. Using curly braces instead of an = sign is one of the many ways to initialize. Using curly braces to initialize a variable also prevents narrowing.
Basically copying and pasting from Bjarne Stroustrup's "The C++ Programming Language 4th Edition":
List initialization does not allow narrowing (§iso.8.5.4). That is:
Example:
void fun(double val, int val2) { int x2 = val; // if val == 7.9, x2 becomes 7 (bad) char c2 = val2; // if val2 == 1025, c2 becomes 1 (bad) int x3 {val}; // error: possible truncation (good) char c3 {val2}; // error: possible narrowing (good) char c4 {24}; // OK: 24 can be represented exactly as a char (good) char c5 {264}; // error (assuming 8-bit chars): 264 cannot be // represented as a char (good) int x4 {2.0}; // error: no double to int value conversion (good) }
The only situation where = is preferred over {} is when using auto
keyword to get the type determined by the initializer.
Example:
auto z1 {99}; // z1 is an int auto z2 = {99}; // z2 is std::initializer_list<int> auto z3 = 99; // z3 is an int
Prefer {} initialization over alternatives unless you have a strong reason not to.
There are already great answers about the advantages of using list initialization, however my personal rule of thumb is NOT to use curly braces whenever possible, but instead make it dependent on the conceptual meaning:
In my experience, this ruleset can be applied much more consistently than using curly braces by default, but having to explicitly remember all the exceptions when they can't be used or have a different meaning than the "normal" function-call syntax with parenthesis (calls a different overload).
It e.g. fits nicely with standard library-types like std::vector
:
vector<int> a{10,20}; //Curly braces -> fills the vector with the arguments vector<int> b(10,20); //Parentheses -> uses arguments to parametrize some functionality, vector<int> c(it1,it2); //like filling the vector with 10 integers or copying a range. vector<int> d{}; //empty braces -> default constructs vector, which is equivalent //to a vector that is filled with zero elements
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With