Pure Software Engineer :)
[Item 7] Distinguising between () and {} when creating objects 본문
Software Engineering/Programming
[Item 7] Distinguising between () and {} when creating objects
HelloJaewon 2014. 12. 5. 19:48int x(0); // initializer is in parentheses int y = 0; // initializer follows "=" int z{0}; // initializer is in braces
The use of an equals sign for initialization often misleads C++ newbies into thinking that an assignment is taking place, even though it's not.
Widget w1; // call default constructor Widget w2 = w1; // not an assignment; calls copy ctor Widget w1 = w2; // an assignment; calls copy operator=
class Widget { ... private: int x{0}; // fine, x's default value is 0 int y = 0; // also fine int z(0); // error! }; std::atomic<int> ai1{0}; // fine std::atomic<int> ai2(0); // fine std::atomic<int> ai3 = 0; // error!
Uniform initialization
C++11 introduces uniform initialization that can, at least in concept, be used anywhere and express everyting.
Of C++'s three ways to designate an initializing expression, only braces can be used every where.
class Widget { ... private: int x{0}; // fine, x's default value is 0 int y = 0; // also fine int z(0); // error! }; std::atomic<int> ai1{0}; // fine std::atomic<int> ai2(0); // fine std::atomic<int> ai3 = 0; // error!
#include <cstdio> #include <vector> #include <string> class Widget { public: Widget () { printf("ctor 0\n"); } Widget (int i, bool b) { printf("ctor 1\n"); } Widget (int i, double d) { printf("ctor 2\n"); } Widget(std::initializer_list<long double> il) { printf("ctor 3\n"); } // Widget(std::initializer_list<bool> il) { // printf("ctor 4\n"); // } // Widget(std::initializer_list<std::string> il) { // printf("ctor 5\n"); // } Widget(const Widget & rhs) { printf("copy ctor\n"); } Widget(const Widget && rhs) { printf("move ctor\n"); } operator float () const { return 1.0f; } }; int main () { Widget w1(10, true); // ctor 1 Widget w2{10, true}; // ctor 3 Widget w3(10, 5.0); // ctor 2 Widget w4{10, 5.0}; // ctor 3 Widget w5(w4); // copy ctor Widget w6{w4}; // ctor 3 Widget w7(std::move(w4)); // move ctor Widget w8{std::move(w4)}; // ctor 3 Widget w9; // ctor 0 Widget w10{}; // ctor 0 // Widget w11(); // vexing parse! Widget w12({}); // ctor 3 Widget w13{{}}; // ctor 3 // use non-std::initializer_list ctor // create 10-element std::vector // all elements have value of 20 std::vector<int> v1(10, 20); // use std::initializer_list ctor // create 2-element std::vector // element values are 10 and 20 std::vector<int> v2{10, 20}; return 0; }
Things to Remember
Braced initialization is the most widely usable initialization syntax, it prevents narrowing conversions, and it's immune to C++'s most vexing parse.During constructor overload resolution, braced initializers are matched to std::initializer_list parameters if at all possible, even if other constructors offer seemingly better match.An example of where the choice between parentheses and braces can make a significant difference is creating a std::vector<numeric type> with two arguments.Choosing between parentheses and braces for object creation inside templates can be challenging.
'Software Engineering > Programming' 카테고리의 다른 글
Facebook Folly Future (0) | 2015.07.19 |
---|---|
[Item 8] Prefer nullptr to 0 and NULL (0) | 2014.12.07 |
Effective Modern C++ (0) | 2014.12.05 |
[C++] 더블 디스패치 (double dispatch) (0) | 2014.10.25 |
[C++] bool vs. enum (0) | 2014.08.11 |