What's the difference between `Object obj(args...)` and `Object obj{args...}`?
c++, c++11, constructor, oop, uniform-initialization
Solution
What's the difference between `Object obj(args...)` and `Object obj{args...}`?
The first is direct-initialization while the second is direct-list-initialization. This is mentioned in two different sections:
§8.5/16 [dcl.init]
The initialization that occurs in the forms
T x(a);
T x{a};
as well as in `new` expressions (5.3.4), `static_cast` expressions (5.2.9), functional notation type conversions (5.2.3), and base and member initializers (12.6.2) is called direct-initialization.
and §8.5.4/1 [dcl.init.list]
List-initialization is initialization of an object or reference from a braced-init-list. Such an initializer is called an initializer list, and the comma-separated initializer-clauses of the list are called the elements of the initializer list. An initializer list may be empty. List-initialization can occur in direct-initialization or copy-initialization contexts; list-initialization in a direct-initialization context is called direct-list-initialization and list-initialization in a copy-initialization context is called copy-list-initialization.
There are a few differences between the two:
If the type being constructed has a constructor that takes an `initializer_list` argument, direct-list-initialization will always favor that constructor. Other constructors will only be considered if the `initializer_list` constructor is not viable. §13.3.1.7/1 [over.match.list]
direct-list-initialization does not allow narrowing conversions within the argument list. §8.5.4/3 [dcl.init.list]
If the type being initialized is an aggregate, direct-list-initialization will perform aggregate initialization. §8.5.4/3 [dcl.init.list]
The order of evaluation of the elements of a braced-init-list is from left to right. §8.5.4/4 [dcl.init.list]
You can avoid the most vexing parse by using direct-list-initialization
struct foo{};
struct bar
{
bar(foo const&) {}
};
bar b1(foo()); // most vexing parse
bar b2(foo{}); // all 3 of the following construct objects of type bar
bar b3{foo()};
bar b4{foo{}};
Problem
The draft book Effective C++11 by Scott Meyers states: Distinguish () and {} when creating objects What's the difference between `Object obj(args...)` and `Object obj{args...}`? and why Scott says so. Update: The question How to use C++11 uniform initialization syntax? asks for HOW, and this question asks for WHY. Update2: I find the following link is helpful and completely answers this question: https://softwareengineering.stackexchange.com/questions/133688/is-c11-uniform-initialization-a-replacement-for-the-old-style-syntax