Search code examples
c++initialization

Is assign with braces the same as call the constructor?


I know that for scalar types you can assign values with braces like int a { 0 };.

This helps with cast, type conversion ecc.

But what for udt? Is

shared_ptr<int> myIntSmartPtr { my_alloc(42), my_free };

the same as

shared_ptr<int> myIntSmartPtr = shared_ptr<int>(my_alloc(42), my_free);

The braces should call the constructor, right?

Is it like an initializer list?

I know what an std::initializer_list is, but it must be the same type T, while in { my_alloc(42), my_free } the types diverge.


Solution

  • This is direct list initialization.

    shared_ptr<int> myIntSmartPtr { my_alloc(42), my_free };
    

    This is an example of the first syntax:

    T object { arg1, arg2, ... };   (1)
    

    The exact effect it has is therefore

    List initialization is performed in the following situations:

    • direct-list-initialization (both explicit and non-explicit constructors are considered)
      1. initialization of a named variable with a braced-init-list (that is, a possibly empty brace-enclosed list of expressions or nested braced-init-lists)

    And for more detail about what that actually means:

    The effects of list-initialization of an object of type T are:

    ... [A bunch of cases that don't apply]

    Otherwise, the constructors of T are considered, in two phases:

    • All constructors that take std::initializer_list as the only argument, or as the first argument if the remaining arguments have default values, are examined, and matched by overload resolution against a single argument of type std::initializer_list
    • If the previous stage does not produce a match, all constructors of T participate in overload resolution against the set of arguments that consists of the elements of the braced-init-list, with the restriction that only non-narrowing conversions are allowed. If this stage produces an explicit constructor as the best match for a copy-list-initialization, compilation fails (note, in simple copy-initialization, explicit constructors are not considered at all).

    std::shared_ptr does not have a constructor that takes an std::initializer_list, so the second bullet point applies and it's constructed from the arguments therein.