Search code examples
c++constructorinitializationlist-initializationuniform-initialization

Object Initialization Syntax in C++ ( T obj = {...} vs T obj{...} )


What is the difference between the two forms of initialization, T obj = {…} and T obj{…}?
I initially thought T obj = {…} was shorthand for T obj = T{…} where a temporary object is copied into our new object. This, although doesn't execute a copy constructor (copy elision), requires its existence and access to it. But when I blocked copy constructor access in this particular class by making the constructor private, there was no error.
This means that there is no copy mechanism involved. So what's the function of the '=' symbol?
I have referred to the following question but was dissatisfied because of the absence of an explanation:
Is C++11 Uniform Initialization a replacement for the old style syntax?

EDIT: On a similar note, is there a difference between int arr[]{…} and int arr[] = {…}? I am asking this to see if I can bring out the contrast between uniform initialization and list initialization.


Solution

  • These have almost exactly the same effect:

    • T x = { 1, 2, 3 };
    • T x { 1, 2, 3 };

    Technically the version with = is called copy-list-initialization and the other version is direct-list-initialization but the behaviour of both of those forms is specified by the list-initialization behaviour.

    The differences are:

    • If copy-list-initialization selects an explicit constructor then the code is ill-formed.
    • If T is auto, then:
      • copy-list-initialization deduces std::initializer_list<Type_of_element>
      • direct-list-initialization only allows a single element in the list, and deduces Type_of_element.

    More information: Why does the standard differentiate between direct-list-initialization and copy-list-initialization?


    If T is an array type then the above still applies; since array list initialization is always aggregate initialization, there is never a constructor selected and so the two versions are the same in all cases.


    T obj = T{...} (excluding auto) is exactly the same as T obj{...}, since C++17, i.e. direct-list-initialization of obj. Prior to C++17 there was direct-list-initialization of a temporary, and then copy-initialization of obj from the temporary.