C++11/C++14 Uniform initialization - 2020
"If you're an experienced C++ programmer and are anything like me, you initially
approached C++11 thinking, "Yes, yes, I get it. It's C++, only more so." But as you
learned more, you were surprised by the scope of the changes. auto declarations,
range-based for loops, lambda expressions, and rvalue references change the face of
C++, to say nothing of the new concurrency features. And then there are the
idiomatic changes. 0 and typedefs are out, nullptr and alias declarations are in.
Enums should now be scoped. Smart pointers are now preferable to built-in ones.
Moving objects is normally better than copying them.
- Effective Modern C++ by Scott Meyers
With C++11, everything can be initialized in much the same way.
- Initialization of dynamically allocated arrays:
int *pi = new int[5]{1, 2, 3, 4, 5};
- Initialization of an array member variable:
class A { int arr[3]; public: A(int x, int y, int z) : arr{x, y, z} { }; };
- Initialization of a STL container:
std::vector v1{1, 2};
- Implicitly initialize objects to return:
return {foo, bar};
- Implicitly initialize a function parameter:
f({foo, bar});
One thing, there are differences in terms of priorities, it's set in this order:
- initializer_list
- regular constructor
- aggregate initialization
#include <iostream> #include <vector> class A { public: int mx; double my; }; class B { public: B(int x, double y) : mx{ x }, my{ y } {} int mx; double my; }; class C { public: C(int x, double y) : mx{ x }, my{ y } {} C(const std::initializer_list<int>& v) { mx = *(v.begin()); my = *(v.begin() + 1); } int mx; double my; }; int main() { // Aggregate initialization A a{ 1, 3.7 }; // Regular constructor B b{ 2, 9.8 }; // Initializer_list C c{ 3, 7 }; std::cout << a.mx << " " << a.my << std::endl; std::cout << b.mx << " " << b.my << std::endl; std::cout << c.mx << " " << c.my << std::endl; return 0; }
The initialization of a 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 necessary. If no conversion exists, or only a narrowing conversion exists, the program is ill-formed. The initialization of b invokes the constructor.
If a class has an initializer list constructor, then it takes priority over other forms of construction.
C++11/C++14 New Features
initializer_list
Uniform initialization
Type Inference (auto) and Range-based for loop
The nullptr and strongly typed enumerations
Static assertions and Constructor delegation
override and final
default and delete specifier
constexpr and string literals
Lambda functions and expressions
std::array container
Rvalue and Lvalue (from C++11 Thread tutorial)
Move semantics and Rvalue Reference (from C++11 Thread tutorial)
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization