C++11 bring with it a great improvement in initializing data. I’ll first cover initializing containers and then move on to more general variable initialization.
Initializer lists
Arrays could always be initialized using C style initialization:
int arr[] = {1,2,3,4,5};
But, that syntax could not be used with containers. That seemed a bit silly given that (e.g.) a std::vector is just a fancy array, so losing features that arrays have is bad. C++11 allows this type of initialization for all containers. You can also add this type of initialization for any of your classes, or even as an argument to a function. This works by the {} initialization works is that it creates an object of a new class std::initializer_list. So for this to be used in your class, you just need to add the relevant constructor. E.g.:
template<class t> class Vec
public:
Vec(std::initializer_list
{
size = i.size(); // set the size of the array in Vec
reserve(size); // allocate the required space in the array
uninitialized_copy(i.begin(), i.end(), array);
}
// ...
Defining a function that takes an initializer list as an argument is similarly easy.
Uniform Initialization
In C++03, initialization of variables was all over the place. Initializer lists improve on that somewhat, but C++11 takes it one step further. Now everything can be initialized in much the same way. Some cases taken straight from the proposal:
- Variable initialization; e.g., X x {v};
- Initialization of a temporary; e.g, X{v}
- Explicit type conversion; e.g. x = X{v};
- Free store allocation; e.g. p = new X{v}
There are a few situations where I see this as being particularly useful:
1. Initialisation of dynamically allocated arrays:
int *p = new int[3]{1,2,3};
2. Initialization of an array member variable:
class C {
int a[3];
public:
C(int x, int y, int z) : a{x, y, z} { /* ... */ };
};
3. Implicitly initialize objects to return:
return {foo, bar};
4. Implicitly initialize a function parameter:
f({foo, bar});
There are some slight traps with the use of this initialization syntax with classes using constructors. For example, take the class C in case #2 above. The following two statements are equivalent:
C c1(1,2,3);
C c2{1,2,3};
However, for std::vector, which is able to be initialized using an initializer list, the following are different:
std::vector
std::vector
How do you initialize this:
template
class Array
{
private:
T array_[N];
public:
Array(const T & value)
: array_( /* initialize every thing with value */ )
{
}
};
In that case I would do an old fashioned…
std::uninitialized_fill(array_, array_ + N, value);
If you don’t have a default construct, it won’t work.