c++ c++11 syntax initialization list-initialization
Updated Fri, 09 Sep 2022 11:28:34 GMT

What are the advantages of list initialization (using curly braces)?

MyClass a1 {a};     // clearer and less error-prone than the other three
MyClass a2 = {a};
MyClass a3 = a;
MyClass a4(a);



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:

  • An integer cannot be converted to another integer that cannot hold its value. For example, char to int is allowed, but not int to char.
  • A floating-point value cannot be converted to another floating-point type that cannot hold its value. For example, float to double is allowed, but not double to float.
  • A floating-point value cannot be converted to an integer type.
  • An integer value cannot be converted to a floating-point type.


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.


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.

Comments (5)

  • +0 – There is also the fact that using () can be parsed as a function declaration. It is confusing and inconsistent that you can say T t(x,y,z); but not T t(). And sometimes, you certain x, you can't even say T t(x);. — Aug 14, 2013 at 05:23  
  • +0 – I strongly disagree with this answer; braced initialization becomes a complete mess when you have types with a ctor accepting a std::initializer_list. RedXIII mentions this issue (and just brushes it off), whereas you completely ignore it. A(5,4) and A{5,4} can call completely different functions, and this is an important thing to know. It can even result in calls that seem unintuitive. Saying that you should prefer {} by default will lead to people misunderstanding what's going on. This isn't your fault, though. I personally think it's an extremely poorly thought out feature. — Feb 02, 2015 at 01:40  
  • +0 – @user1520427 That's why there's the "unless you have a strong reason not to" part. — Feb 02, 2015 at 16:54  
  • +0 – Although this question is old it has quite a few hit thus I'm adding this here just for reference ( I haven't seen it anywhere else in the page ). From C++14 with the new Rules for auto deduction from braced-init-list it is now possible to write auto var{ 5 } and it will be deduced as int no more as std::initializer_list<int>. — Oct 31, 2015 at 12:26  
  • +0 – Haha, from all the comments it's still not clear what to do. What is clear is, that the C++ specification is a mess! — Mar 12, 2019 at 13:19