Uniform Initialization

C++11 extends the applicability of the brace-enclosed list (list-initialization) so that it can be used with all built-in types and with user-defined types (that is, class objects). The list can be used either with or without the = sign:

int x = {5};
double y {2.75};
short quar[5] {4,5,2,76,1};

Also the list-initialization syntax can be used in new expressions:

int * ar = new int [4] {2,4,6,7};         // C++11

With class objects, a braced list can be used instead of a parenthesized list to invoke a constructor:

class Stump
{
private:
    int roots;
    double weight;
public:
     Stump(int r, double w) : roots(r), weight(w) {}
};
Stump s1(3,15.6);      // old style
Stump s2{5, 43.4};     // C++11
Stump s3 = {4, 32.1};  // C++11

However, if a class has a constructor whose argument is a std::initializer_list template, then only that constructor can use the list-initialization form. Various aspects of list-initialization were discussed in Chapters 3, 4, 9, 10, and 16.

Narrowing

The initialization-list syntax provides protection against narrowing—that is, against assigning a numeric value to a numeric type not capable of holding that value. Ordinary initialization allows you to do things that may or may not make sense:

char c1 = 1.57e27;   // double-to-char, undefined behavior
char c2 = 459585821; // int-to-char, undefined behavior

If you use initialization-list syntax, however, the compiler disallows type conversions that attempt to store values in a type “narrower” than the value:

char c1 {1.57e27};    // double-to-char, compile-time error
char c2 = {459585821};// int-to-char,out of range, compile-time error

However, conversions to wider types are allowed. Also a conversion to a narrower type is allowed if the value is within the range allowed by the type:

char c1 {66};     // int-to-char, in range, allowed
double c2 = {66}; // int-to-double, allowed

std::initializer_list

C++11 provides an initializer_list template class (discussed in Chapter 16, “The string Class and the Standard Template Library”) that can be used as a constructor argument. If a class has such a constructor, the brace syntax can be used only with that constructor. The items in the list should all be of the same type or else be convertible to the same type. The STL containers provide constructors with initializer_list arguments:

vector<int> a1(10);    // uninitialized vector with 10 elements
vector<int> a2{10};    // initializer-list, a2 has 1 element set to 10
vector<int> a3{4,6,1}; // 3 elements set to 4,6,1

The initializer_list header file provides support for this template class. The class has begin() and end() member functions specifying the range of the list. You can use an initializer_list argument for regular functions as well as for constructors:

#include <initializer_list>
double sum(std::initializer_list<double> il);
int main()
{
   double total = sum({2.5,3.1,4});  // 4 converted to 4.0
...
}
double sum(std::initializer_list<double> il)
{
    double tot = 0;
    for (auto p = il.begin(); p !=il.end(); p++)
        tot += *p;
    return tot;
}

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.107.100