C++ has a lot of way of initializing an object but prior to C++11 there was no single way of initialization applicable to all type of objects. That was the motivation to find a single way of initialization in C++11. Novice programmers may get confused with initialization and assignment operations. When we initialize with an assignment (=) sign someone may take it as assignment operation. But remember assignment operation and initialization operation are different- Code: int i = 0; // It is not assignment but initialization int j = i; //It is again initialization int k; //Uninitialized k = j; // This is not initialization but assignment The difference may be academic for built-in types but for user defined type like class, it is very important to remember that different methods are called for different operations. For initialization constructor, copy constructor or move constructor are called and for assignment, assignment operator or move assignment operator are called. The following code snippet using a class MyClass is showing how initialization and assignment differs: Code: //Initialization MyClass obj1; // Constructor is called MyClass obj2 = obj1; // Copy constructor is called MyClass obj3 = std::move(obj1); // Move constructor is called // Assignment obj2 = obj1; //Assignment operator is called obj2 = MyClass();// Move assignment operator is called Want to run and see the code? Here is the class definition: Code: #include<iostream> #include<vector> using namespace std; class MyClass { private: static int instancecount; const int data; public: //Default constructor MyClass() :data(0) { cout << "+ Default Constructor()" << endl; cout << "New instance of MyClass is created" << endl; cout << "Number of instances: " << ++instancecount << endl; cout << "- Default Constructor()" << endl<<endl; } //Parameterized constructor MyClass(int value) :data(value) { cout << "+ Parameterize Constructor()" << endl; cout << "New instance of MyClass is created" << endl; cout << "Number of instances: " << ++instancecount << endl; cout << "- Parameterize Constructor()" << endl<<endl; } //Default copy constructor MyClass(const MyClass& source) :data(source.data) { cout << "+ Default copy Constructor ()" << endl; cout << "New instance of MyClass is created" << endl; cout << "Number of instances: " << ++instancecount << endl; cout << "- Default copy Constructor ()" << endl<<endl; } //Move constructor MyClass(MyClass&& source) :data(source.data) { cout << "+ Move Constructor ()" << endl; cout << "New instance of MyClass is created " << endl; cout << "Number of instances: " << ++instancecount << endl; cout << "- Move Constructor ()" << endl<<endl; } //Default copy assignment operator MyClass& operator =(MyClass& source) { cout << "+ copy assignment operator ()" << endl; cout << "- copy assignment operator ()" << endl<<endl; return *this; } //Move assignment operator MyClass& operator =(MyClass&& source) { cout << "+ Move assignment operator ()" << endl; cout << "- Move assignment operator ()" << endl << endl; return *this; } ~MyClass() { cout << "+ Destructor ()" << endl; cout << "One instance of MyClass is destroyed" << endl; cout << "Number of instances: " << --instancecount << endl; cout << "- Destructor ()" << endl<<endl; } }; int MyClass::instancecount = 0; //intializayion Now we know the difference of initialization and assignment, Let us see what are the ways to initialize a variable: Code: int i= 0; //Initialize to zero int i(0); //Initialize to zero int i = int(0); //Initialize to zero int i{ 0 }; //Initialize to zero Code: MyClass obj(); //It treats as a function deceleration, confusing, isn’t it? MyClass obj(0); //Create object and calls constructor MyClass obj1(obj);//Create object and calls copy constructor MyClass obj1=obj;//Create object and calls copy constructor MyClass obj1 = MyClass();//Create object and calls constructor So which method do you adopt for initialization? Every time you write code, you might be wasting time to think about which initialization is to be used. Even you fix your mind to use only one method there is no single way to initialize all type of data structures in C++98.For example if you declare a vector with initial set of value you cannot do it in C++98. You have to write following code- Code: std::vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); But in C++11 you can initialize it: Code: std::vector<int> v{1,2,3,5}; // v will initially have 4 items and contents will be 1,2,3 and 5. This is called brace initialization. C++11 made the brace initialization applicable to all type of data and recommends to use it and not use other methods. This uniform initialization method is solving 2 problems, one is to remove the confusion of selecting of a particular initialization method and the other is initializing is possible for types which was not possible previously: Following decelerations show how braced initialization is used for all types of data: Code: int i{ 0 }; //Initialize to zero int j{}; //Initialize to zero std::vector<int>v{ 1,3,5 };// Initialize the vector with 3 elements std::vector<MyClass>{}; //Empty vector std::vector<MyClass>{MyClass{ 1 }, MyClass{ 2 }, MyClass{3}};// Initialize the vector with 3 MyClass elements MyClass obj{ }; //Create object and calls default constructor, if default constructor is not there then error MyClass obj1{ 10 }; //Create object and calls constructor with one argument MyClass obj2{ obj };//Create object and calls copy constructor MyClass obj3{ std::move(obj) };//Create object and calls move constructor struct S { int x; int y; }; S s{ 2 };//Initializes s with x=2,y=0 S s{ 2,4 };//Initializes s with x=2,y=4 S s{ 2,4,5 };//Error: too many initializer values int arr[3]{ 2,4,6 };//Initializes arr with 2,4 and 6 int arr[3]{ 2,4 };//Initializes arr with 2,4 and 0 int arr[3]{ 2,4,6,8 };//Error: too many initializer values string str{"Hello"}; // Uses constructor string str2{str}; // Uses copy constructor map<int, string> mymap{ {1,"Aple"},{2,"Orrange"},{3,"Mango"} };// Creates and initialises the map of size 3 int* p = new int[3]{ 1,5,8 };//Allocates memory for elements and intializes the elemnts to 1,5 and 8 int *ptr{};//initializes the prt to nulptr char s2[10]{};//Initializes all characters to '\0' class C1 { int val[3]{0,1,2}; // member initialization public: C1() : val{ 0,1,2 } {};//Over rides the member initialization }; Braced initialization prohibits implicit narrowing conversions among built-in types. For example: Code: int i = 3 + 4.5 + 4; // OK int i2 (3 + 4.5 + 4);//OK int j{ 3 + 4.5 + 4 };// Error: narrowing conversion not allowed With braced initialization you can avoid ambiguous syntax of parenthesis initialization like: Code: MyClass obj(0);// Calls the constructor with one argument MyClass obj();// Does not create MyClass object rather declares a function obj() which returns MyClass With braced initialization it works- Code: MyClass obj{ 0 };// Calls the constructor with one argument MyClass obj{};// Calls the default constructor Understanding the braced initialization process will not be complete unless you know about std::initializer_list<T> template and it’s relation with braced initialization ( {} ). Look at the following code: Code: auto mylist={1,2,3,4}; Here the type of mylist is deduced to be std::initializer_list<int>. Actually braced initialization creates a std::initializer_list object by default if not specified otherwise. If you have overloaded methods with std::initializer_list as argument for one of the overloaded methods, braced initialization will match the version with std::initializer_list as argument. Suppose you have the following two overloaded functions - Code: void myfn(vector<int> v) { cout << "Calling with vector argument" << endl; } void myfn(initializer_list<int> il) { cout << "Calling with list argument" << endl; } And you call the finction like: myfn({1, 2, 3}); will invoke the 2nd function. This scenario you will face while initializing a vector shown below Code: vector<int> v(10, 4);//Will call the constructor which adds 10 elements and initialize each element with value 4 vector<int> v2{ 10,4 };//Will call the constructor with std::initializer_list<int> which add 2 element 10 and 4 This behavior can lead to unexpected behavior when braced initialization is used with class having overloaded constructors having std::initializer_list<T> type argument. While implementing a class having overloaded constructors or methods with std::initializer_list<T> type argument you should be aware of the implication of braced initialization.