Initializing objects with new {} syntax like this:
int a { 123 };
has benefit - you would not declare a function instead of creating a variable by mistake. I even heard that it should be habit to always do that. But see what could happen:
// I want to create vector with 5 ones in it:
std::vector<int> vi{ 5, 1 }; // ups we have vector with 5 and 1.
Is this good habit then? Is there a way to avoid such problems?
Frankly, the subtleties of the various initialization techniques make it difficult to say that any one practice is a "good habit."
As mentioned in a comment, Scott Meyers discusses brace-initialization at length in Modern Effective C++. He has made further comments on the matter on his blog, for instance here and here. In that second post, he finally says explicitly that he thinks the morass of C++ initialization vagaries is simply bad language design.
As mentioned in 101010's answer, there are benefits to brace-initialization. The prevention of implicit narrowing is the main benefit, in my opinion. The "most vexing parse" issue is of course a genuine benefit, but it's paltry--it seems to me that in most cases an incorrect int a();
instead of int a;
would probably be caught at compile time.
But there are at least two major drawbacks:
auto
always deduces std::initializer_list
from a brace-initializer. In C++17, if there's only one element in the initialization list, and =
is not used, auto
deduces the type of that element; C++17
rules for auto
with brace initialization is still not quite right.) All of these behaviors are somewhat surprising and (in mine and Scott Meyers' opinions) annoying and perplexing.std::vector<int> vi{ 5, 1 };
is surprising to people familiar with vector
's old two-element constructor. Scott Meyers lists some other examples in Effective Modern C++. Personally, I find this even worse than the auto
deduction behavior (I generally only use auto
with copy initialization, which makes the first issue fairly easy to avoid).EDIT: It turns out that stupid compiler-implementation decisions can sometimes be another reason to use brace-initialization (though really the #undef
approach is probably more correct).