list can be copied once constructed, which is cheap and will act as a copy-by-reference (the class is typically implemented as a pair of begin/end pointers). An std::initializer_list is constant: its members cannot be changed once it is created, and nor can the data in those members be changed (which rules out moving from them, requiring copies into class members, etc.). Although its construction is specially treated by the compiler, an std::initializer_list is a real type, and so it can be used in other places besides class constructors. Regular functions can take typed std::initializer_lists as arguments. For example: void function_name(std::initializer_list<float> list); // Copying is cheap; see above function_name({1.0f, -3.45f, -0.4f}); Examples of this in the standard library include the std::min() and std::max() templates taking std::initializer_lists of numeric type. Standard containers can also be initialized in these ways: std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" }; std::vector<std::string> v({ "xyzzy", "plugh", "abracadabra" }); std::vector<std::string> v{ "xyzzy", "plugh", "abracadabra" }; // see "Uniform initialization" below Uniform initialization C++03 has a number of problems with initializing types. Several ways to do this exist, and some produce different results when interchanged. The traditional constructor syntax, for example, can look like a function declaration, and steps must be taken to ensure that the compiler's most vexing parse rule will not mistake it for such. Only aggregates and POD types can be initialized with aggregate initializers (using SomeType var = {/*stuff*/};). C++11 provides a syntax that allows for fully uniform type initialization that works on any object. It expands on the initializer list syntax: struct BasicStruct { int x; double y; }; struct AltStruct { AltStruct(int x, double y) : x_{x} , y_{y} {} private: int x_; double y_; }; BasicStruct var1{5, 3.2}; AltStruct var2{2, 4.3}; The initialization of var1 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 needed. If no conversion exists, or only a narrowing conversion exists, the program is ill-formed. The initialization of var2 invokes the constructor. One can also do this: struct IdString { std::string name; int identifier; }; IdString get_string() { return {"foo", 42}; //Note the lack of explicit type. } Uniform initialization does not replace constructor syntax, which is still needed at times. If a class has an initializer list constructor (TypeName(initializer_list<SomeType>);), then it takes