int a; // undefined value
int b(5); // direct initialization, b = 5
int c = 10; // copy initialization, c = 10
int d = int(); // default initialization, d = 0
int e(); // function declaration - "most vexing parse"
int values[] = { 1, 2, 3, 4 }; // brace initialization of aggregate
int array[] = { 1, 2, 3.5 }; // C++98 - ok, implicit type narrowing
struct P { int a, b; };
P p = { 20, 40 }; // brace initialization of POD
std::complex<double> c(4.0, 2.0); // initialization of classes
std::vector<std::string> names; // no initialization for list of values
names.push_back("John");
names.push_back("Jane");
int a; // still undefined value
int b{5}; // brace initialization, b = 5
int c{}; // brace initialization, c = 0
int values[] = { 1, 2, 3, 4 }; // brace initialization of aggregate
int array[] = { 1, 2, 3.5 }; // C++11: error - implicit type narrowing
struct P { int a, b; };
P p = { 20, 40 }; // brace initialization of POD
std::complex<double> c{4.0, 2.0}; // brace initialization calls adequate c-tor
std::vector<std::string> names = { "John", "Jane" }; // brace initialization of vector
Rationale: eliminate problematic initialization cases from C++98, initialization of STL containers, have one universal way of initialization.
struct Foo
{
Foo() {}
Foo(std::string a) : a_(a) {}
void print() { std::cout << a_ << std::endl; }
private:
std::string a_ = "Foo"; // C++98: error, C++11: OK
static const unsigned VALUE = 20u; // C++98: OK, C++11: OK
};
Foo().print(); // Foo
Foo("Bar").print(); // Barauto values = {1, 2, 3, 4, 5}; // values is std::initializer_list<int>
std::vector<int> v = {1, 2, -3}; // creates a vector from
// std::initializer_list<int>-
Defined in
initializer_listheader - Elements are kept in an array
- Elements are immutable
- Elements must be copyable
-
Have limited interface and access via iterators -
begin(),end(),size() - Should be passed to functions by value
template<class Type>
class Bar {
std::vector<Type> values_;
public:
Bar(std::initializer_list<Type> values) : values_(values) {}
Bar(Type a, Type b) : values_{a, b} {}
};
Bar<int> c = {1, 2, 5, 51}; // calls std::initializer_list c-tor
Bar<int> d{1, 2, 5, 51}; // calls std::initializer_list c-tor
Bar<int> e = {1, 2}; // calls std::initializer_list c-tor
Bar<int> f{1, 2}; // calls std::initializer_list c-tor
Bar<int> g(1, 2); // calls Bar(Type a, Type b) c-tor
Bar<int> h = {}; // calls std::initializer_list c-tor
// or default c-tor if exists
Bar<std::unique_ptr> c = {new int{1}, new int{2}};
// error - std::unique_ptr is non-copyable
C-tor with std::initializer_list has greater priority, even if other c-tors match.
Use initializer_list to initialize the collection.
Add a new constructor to Shape - Shape(Color c). What happens?
Use constructor inheritance to allow initialization of all shapes providing only a Color as a parameter.
Create some shapes providing a Color only param.
Add in-class field initialization for all shapes to safely use inherited constructor.