6

Up until now, I have been initializing most of my variables as such:

const QString foo("bar");

Which from my newfound understanding, is known as direct initialization. (http://en.cppreference.com/w/cpp/language/direct_initialization)

I was looking at someone's code, and in a namespace, they were initializing their variables with Curly Braces:

const QString foo{"bar"};

which also counts as direct initialization: enter image description here

I never knew this was a thing until today.

Code is more often read than written, what does direct initialization with Curly Braces imply as compared to Parentheses?

Just as I understand a const will tell me that a variable will not change, can I infer anything from this curly brace practice?

Anon
  • 3,639

2 Answers2

8

This shows that the author is using modern C++ (e.g. >= C++11) and applies good practice:

Braced initialization is the most widely usable initialization syntax, it prevents narrowing conversions and it's immune to C++'s most vexing parse.

-- Scott Meyers, in Effective Modern C++, Item 7

You have to be aware that there might however be a subtlety if a class has a constructor from an initializer list.

If you're not familiar with this syntax, I'd really recommend you to read Scott Meyer's above-mentioned book or acquire equivalent knowledge for example with Herb Sutter's videos, in order not to end up with outdated C++ skills.

Christophe
  • 81,699
1

I don't think you can infer much of anything. There are simply too many possibilities here to draw a meaningful inference.

First, keep in mind that all along, aggregates could be initialized using braces:

struct foo { 
    int x;
    long y;
};

// well formed since long before C++ existed:    
foo bar = { 1, 2 };

// New syntax
foo baz { 2, 3 };

So, the only difference in this case is leaving out the = between the name of the variable, and the initializer. That's kind of convenient, but doesn't really mean much. This could literally be a case of intending to use the old syntax, missing the = due to a typo, and never correcting/noticing it because the compiler didn't give an error message.

With that in mind, let's consider the cases where you once had to use parens instead of braces.

struct abc { 
    int x;
    abc(int x) : x(x) {}
};

So this, under C++ 98/03, we did initialization something like this:

abc def(1);

Now we can use:

abc def = {1};

or:

abc def{1};

Again, I think it's entirely possible that in a fair number of cases, the abc def = {1}; case happens entirely by accident. Somebody wrote it without checking whether abc was an aggregate or not. At one time, the compiler would have complained and they'd have changed it to get it to compile. The compiler no longer complains, so they leave it alone.

Don't get me wrong: I'm all in favor of preventing narrowing conversions1. But, given human nature (and the amount of C++ I see written without knowing all the intimate details of the standard, not to mention all its most recent changes) I think there are probably a fair number of cases where things like this happen more or less by accident, and since they work they're left alone.


1. I'm a lot less excited about everything being interpreted as an initializer_list if at all possible though.

Jerry Coffin
  • 44,795