C++11 introduces braced initialization as the preferred way for initialization.
Existing initialization and assignment syntaxes -
1. int x(0); //Ok, initialization in paranthesis
2. int x = 0; //Ok, initialization using =
3. double a, b, c;
int x(a + b + c); //Ok, sum of double's may not fit an int, the sum is then truncated
int x = a + b + c; //Ok, same as above
4. string s; //Ok, default ctor call for string class
5. string s("init"); //Ok, initialize s
6. string s(); //this is not initialize with default value, rather it declares a function named s which returns a string
7. string s2 = s1; //Ok, copy ctor is used (not assignment operator)
8. s3 = s2; //assignment operator
9. class ABC {
private: //initializing non-static data members of the class
int x = 0; //Ok
int y(0); //error
};
Braced initialization solves these issues and brings consistency -
1. int x{0}; //Ok, initializer in braces
2. int x = {0}; //Ok, same as above
3. double a, b, c;
int x(a + b + c); //Error, narrowing not allowed
4. string s{}; //Equivalent to #4 above
5. string s{"init"}; //Equivalent to #5 above
6. string s{}; //No longer declares a function, rather same as #4 above
7. class ABC {
private:
int x{0}; //same as #9 above
int y{0};
};
Additionally, braced initialization can be used to initialize uncopyable objects -
std::atomic<int> x{0};
std::atomic<int> x(0); //Ok
std::atomic<int> x = 0; //Error
Braced initializers can lead to confusion when std::intializer_list constructors are involved. Example -
class ABC {
public:
ABC(int i, int j);
ABC(std::initializer_list<int> k);
};
ABC(1, 2); //calls the first ctor
ABC{1, 2}; //calls the second ctor
Existing initialization and assignment syntaxes -
1. int x(0); //Ok, initialization in paranthesis
2. int x = 0; //Ok, initialization using =
3. double a, b, c;
int x(a + b + c); //Ok, sum of double's may not fit an int, the sum is then truncated
int x = a + b + c; //Ok, same as above
4. string s; //Ok, default ctor call for string class
5. string s("init"); //Ok, initialize s
6. string s(); //this is not initialize with default value, rather it declares a function named s which returns a string
7. string s2 = s1; //Ok, copy ctor is used (not assignment operator)
8. s3 = s2; //assignment operator
9. class ABC {
private: //initializing non-static data members of the class
int x = 0; //Ok
int y(0); //error
};
Braced initialization solves these issues and brings consistency -
1. int x{0}; //Ok, initializer in braces
2. int x = {0}; //Ok, same as above
3. double a, b, c;
int x(a + b + c); //Error, narrowing not allowed
4. string s{}; //Equivalent to #4 above
5. string s{"init"}; //Equivalent to #5 above
6. string s{}; //No longer declares a function, rather same as #4 above
7. class ABC {
private:
int x{0}; //same as #9 above
int y{0};
};
Additionally, braced initialization can be used to initialize uncopyable objects -
std::atomic<int> x{0};
std::atomic<int> x(0); //Ok
std::atomic<int> x = 0; //Error
Braced initializers can lead to confusion when std::intializer_list constructors are involved. Example -
class ABC {
public:
ABC(int i, int j);
ABC(std::initializer_list<int> k);
};
ABC(1, 2); //calls the first ctor
ABC{1, 2}; //calls the second ctor