Uniform initialization - 2020
Bookmark and Share


Uniform initialization

With C++11, everything can be initialized in much the same way.

  • Initialization of dynamically allocated arrays:
    int *pi = new int[5]{1, 2, 3, 4, 5};
    
  • Initialization of an array member variable:
    class A {
      int arr[3];
    public:
      A(int x, int y, int z) : arr{x, y, z} { };
    };
    
  • Initialization of a STL container:
     std::vector v1{1, 2};
    
  • Implicitly initialize objects to return:
    return {foo, bar};
    
  • Implicitly initialize a function parameter:
    f({foo, bar});
    

One thing, there are differences in terms of priorities, it's set in this order:

  1. initializer_list
  2. regular constructor
  3. aggregate initialization
#include <iostream>
#include <vector>

class A
{
public:
	int mx;
	double my;
};

class B
{
public:
	B(int x, double y) : mx{ x }, my{ y } {}

	int mx;
	double my;
};

class C
{
public:
	C(int x, double y) : mx{ x }, my{ y } {}
	C(const std::initializer_list<int>& v) {
		mx = *(v.begin());
		my = *(v.begin() + 1);
	}

	int mx;
	double my;
};

int main()
{
	// Aggregate initialization
	A a{ 1, 3.7 };

	// Regular constructor
	B b{ 2, 9.8 };

	// Initializer_list
	C c{ 3, 7 };

	std::cout << a.mx << " " << a.my << std::endl;
	std::cout << b.mx << " " << b.my << std::endl;
	std::cout << c.mx << " " << c.my << std::endl;

	return 0;
}

The initialization of a behaves exactly as though it were aggregate-initialization. That is, each data member of an object, in turn, will be copy-initialized with the corresponding value from the initializer-list.

Implicit type conversion will be used where necessary. If no conversion exists, or only a narrowing conversion exists, the program is ill-formed. The initialization of b invokes the constructor.

If a class has an initializer list constructor, then it takes priority over other forms of construction.