C++备忘录059:() or {} During Initializaition gist of "Effective Modern C++"

As a general rule, initialization values may be specified with parentheses, an equals sign, or braces.

uniform/braced initialization

struct Widget {
    int x{0};
    int y = 0;
    int z(0);   // error! 
};

Widget w1;      // default ctor
Widget w2 = w1; // copy ctor
w1 = w2;        // copy operator=

// uncopyable objects may be intialized using braces or parentheses, but not using =
std::atomic<int> ai1{0};
std::atomic<int> ai2(0);
std::atomic<int> ai3 = 0;   // error
It prohibits implicit narrowing conversions among built-in types.
double x, y, z;
int sum1{x + y + z};    // error!

int sum2(x + y + z);    // okay (value of expression truncated to an int)
int sum3 = x + y + z;   // ditto
Widget w1(10);  // call ctor
Widget w2();    // most vexing parse!
Widget w3{};    // call ctor

Braced initialization is the syntax that can be used in the widest variety of contexts, it prevents implicit narrowing conversion, and it’s immune to C++'s most vexing parse.

The pitfall
class Widget {
public:
    Widget(int i, bool b);
    Widget(int i, double d);
};

Widget w1(10, true);    // first ctor
Widget w2{10, true};    // ditto

Widget w3(10, 5.0);     // second ctor
Widget w4{10, 5.0};     // ditto

*If there’s any way for compilers to construe a call using a branced initializer to be to a constructor taking a std::initializer_list, compilers will employ that interpretation.

class Widget {
public:
    Widget(int i, bool b);
    Widget(int i, double d);
    Widget(std::initializer_list<long double> il);  // added
};

Widget w1(10, true);    // first ctor, as before
Widget w2{10, true};    // std::initializer_list ctor (10 and true convert to long double)

Widget w3(10, 5.0);     // second ctor, as before
Widget w2{10, 5.0};    // std::initializer_list ctor (10 and 5.0 convert to long double)
class Widget {
public:
    Widget(int i, bool b);
    Widget(int i, double d);
    Widget(std::initializer_list<long double> il);

    operator float() const; // added
};

Widget w5(w4);  // copy ctor
Widget w6{w4};  // std::initializer_list ctor (w4 converts to float, and float converts to long double)
class Widget {
public:
    Widget(int i, bool b);
    Widget(int i, double d);
    Widget(std::initializer_list<bool> il);
};

Widget w{10, 5.0};  // error! 10 and 5.0 is convertible but need narrowing conversion

Only if there is no way to convert the types of the arguments in a braced initialzier to the type in std::initializer_list do compilers fall back on normal overload resolution.

class Widget {
public:
    Widget(int i, bool b);
    Widget(int i, double d);
    Widget(std::initializer_list<std::string> il);  // no implicit conversion
};

Widget w1(10, true);    // first ctor
Widget w2{10, true};    // first ctor
Widget w3(10, 5.0);     // second ctor
Widget w4{10, 5.0};     // second ctor
class Widget {
public:
    Widget();
    Widget(std::initializer_list<int> il);
};

Widget w1;      // default ctor
Widget w2{};    // default ctor

Widget w3();    // most vexing parse 

Widget w4({});  // std::initializer_list ctor
Widget w5{{}};  // ditto

Notes

struct Widget {
	Widget() = delete;
};

Widget w1;		// Error
Widget w2{};	// Ok in C++17, will be fixed in C++20
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值