Guidelines For Initialisation
This is a combination of Herb Sutter’s GotW #1 and Abseil Tip #88.
There are about 18 ways to initialise a variable in C++. Especially given C++ 11’s uniform initialisation syntax it’s getting pretty complicated. Use the following guidelines when trying to initialise a local or member variable:
Use {} Syntax With =
Using the uniform initialisation syntax avoids a few C++ pitfalls, namely the most vexing parse and narrowing conversions. Combined with the assignment operator it ensures that it won’t accidentily call un-intended constructors and is especially useful for list initialisation. Similarly, it should be used for aggregate initialisation of structs as well.
std::vector<int> numbers = {1, 2, 3, 4};
auto numbers = std::vector<int>{1, 2, 3, 4};
auto copyString = std::string{otherString};
SimpleStruct triv = {val1, val2};
Use () If Using a Specific Non-Default Constructor
If you’re calling a specific constructor with specific behaviour that does not use an initializer list, then use the usual parentheses syntax.
auto const resizeNum = 15;
auto const defaultVal = 42;
// Both lines don't have to use =
auto numbers = std::vector<int>(resizeNum, defaultVal);
auto symbol = Symbol(display_prop, texture);
Use {} Without = If Above Options Don’t Compile
If a constructor is marked explicit or is non-copyable / non movable then you can initialize without an assignment statement. C++ 17 alleviates a few of these concerns and should allow for using = even if it is non-copyable.
NonCopyType local_var{42, other_variable}; // OK
// Both lines below are weird cases
// Do do that
auto number{42};
auto value = {42};