Properly initialising variables in modern C++ (C++11 and above), using () or {}?

前端 未结 7 973

The C++ reference pages say that () is for value initialisation, {} is for value and aggregate and list initialisation. So, if I just want value initialisation, which one do

相关标签:
7条回答
  • 2020-12-13 18:40

    There is another important difference: The brace initializer requires that the given type can actually hold the given value. In other words, it forbids narrowing of the value, like rounding or truncation.

    int a(2.3); // ok? a will hold the value 2, no error, maybe compiler warning
    uint8_t c(256); // ok? the compiler should warn about something fishy going on
    

    As compared to the brace initialization

    int A{2.3}; // compiler error, because int can NOT hold a floating point value
    double B{2.3}; // ok, double can hold this value
    uint8_t C{256}; // compiler error, because 8bit is not wide enough for this number
    

    Especially in generic programming with templates you should therefore use brace initialization to avoid nasty surprises when the underlying type does something unexpected to your input values.

    0 讨论(0)
  • 2020-12-13 18:43

    {} is value initialization if empty, if not it is list/aggregate initialization.

    From the draft, 7.1.6.4 auto specifier, 7/... Example,

    auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>

    Rules are a little bit complex to explain here (even hard to read from the source!).

    0 讨论(0)
  • 2020-12-13 18:51

    Scott Mayers just posted a relevant blog entry Thoughts on the Vagaries of C++ Initialization. It seems that C++ still has a way to go before achieving a truly uniform initialization syntax.

    0 讨论(0)
  • 2020-12-13 18:54

    First off, there seems to a terminology mixup. What you have is not value initialisation. Value initialisation happens when you do not provide any explicit initialisation arguments. int x; uses default initialisation, the value of x will be unspecified. int x{}; uses value initialisation, x will be 0. int x(); declares a function—that's why {} is preferred for value initialisation.

    The code you've shown does not use value initialisation. With auto, the safest thing is to use copy initialisation:

    auto q = p;
    
    0 讨论(0)
  • 2020-12-13 18:56

    Herb Sutter seems to be making an argument in CppCon 2014 (39:25 into the talk) for using auto and brace initializers, like so:

    auto x = MyType { initializers };
    

    whenever you want to coerce the type, for left-to-right consistency in definitions:

    • Type-deduced: auto x = getSomething()
    • Type-coerced: auto x = MyType { blah }
    • User-defined literals auto x = "Hello, world."s
    • Function declaration: auto f { some; commands; } -> MyType
    • Named Lambda: using auto f = [=]( { some; commands; } -> MyType
    • C++11-style typedef: using AnotherType = SomeTemplate<MyTemplateArg>
    0 讨论(0)
  • 2020-12-13 18:57

    Scott Meyers has a fair amount to say about the difference between the two methods of initialization in his book Effective Modern C++.

    He summarizes both approaches like this:

    Most developers end up choosing one kind of delimiter as a default, using the other only when they have to. Braces-by-default folks are attracted by their unrivaled breadth of applicability, their prohibition of narrowing conversions, and their immunity to C++’s most vexing parse. Such folks understand that in some cases (e.g., creation of a std::vector with a given size and initial element value), parentheses are required. On the other hand, the go-parentheses-go crowd embraces parentheses as their default argument delimiter. They’re attracted to its consistency with the C++98 syntactic tradition, its avoidance of the auto-deduced-a-std::initializer_list problem, and the knowledge that their object creation calls won’t be inadvertently waylaid by std::initializer_list constructors. They concede that sometimes only braces will do (e.g., when creating a container with particular values). There’s no consensus that either approach is better than the other, so my advice is to pick one and apply it consistently.

    0 讨论(0)
提交回复
热议问题