mirror of
https://github.com/CnTransGroup/EffectiveModernCppChinese.git
synced 2025-01-27 20:30:28 +08:00
a small fix
This commit is contained in:
parent
933dd27182
commit
d4bbc7bf05
@ -72,7 +72,7 @@ int sum2(x + y +z); //可以(表达式的值被截为int)
|
||||
|
||||
int sum3 = x + y + z; //同上
|
||||
````
|
||||
另一个值得注意的特性是括号表达式对于C++最令人头疼的解析问题有天生的免疫性。(译注:所谓最令人头疼的解析即_most vexing parse_,更多信息请参见[https://en.wikipedia.org/wiki/Most_vexing_parse](https://en.wikipedia.org/wiki/Most_vexing_parse)。)C++规定任何能被决议为一个声明的东西必须被决议为声明。这个规则的副作用是让很多程序员备受折磨:当他们想创建一个使用默认构造函数构造的对象,却不小心变成了函数声明。问题的根源是如果你想使用一个实参调用一个构造函数,你可以这样做:
|
||||
另一个值得注意的特性是括号表达式对于C++最令人头疼的解析问题有天生的免疫性。(译注:所谓最令人头疼的解析即*most vexing parse*,更多信息请参见[https://en.wikipedia.org/wiki/Most_vexing_parse](https://en.wikipedia.org/wiki/Most_vexing_parse)。)C++规定任何能被决议为一个声明的东西必须被决议为声明。这个规则的副作用是让很多程序员备受折磨:当他们想创建一个使用默认构造函数构造的对象,却不小心变成了函数声明。问题的根源是如果你想使用一个实参调用一个构造函数,你可以这样做:
|
||||
|
||||
````cpp
|
||||
Widget w1(10); //使用实参10调用Widget的一个构造函数
|
||||
@ -153,10 +153,10 @@ Widget w8{std::move(w4)}; //使用花括号,调用std::initializer_list构造
|
||||
编译器热衷于把括号初始化与使`std::initializer_list`构造函数匹配了,尽管最佳匹配`std::initializer_list`构造函数不能被调用也会凑上去。比如:
|
||||
````cpp
|
||||
class Widget {
|
||||
public:
|
||||
Widget(int i, bool b); //同之前一样
|
||||
Widget(int i, double d); //同之前一样
|
||||
Widget(std::initializer_list<bool> il); //现在元素类型为bool
|
||||
public:
|
||||
Widget(int i, bool b); //同之前一样
|
||||
Widget(int i, double d); //同之前一样
|
||||
Widget(std::initializer_list<bool> il); //现在元素类型为bool
|
||||
... //没有隐式转换函数
|
||||
};
|
||||
|
||||
@ -169,11 +169,11 @@ Widget w{10, 5.0}; //错误!要求变窄转换
|
||||
````cpp
|
||||
class Widget {
|
||||
public:
|
||||
Widget(int i, bool b); //同之前一样
|
||||
Widget(int i, double d); //同之前一样
|
||||
//现在std::initializer_list元素类型为std::string
|
||||
Widget(int i, bool b); //同之前一样
|
||||
Widget(int i, double d); //同之前一样
|
||||
//现在std::initializer_list元素类型为std::string
|
||||
Widget(std::initializer_list<std::string> il);
|
||||
... //没有隐式转换函数
|
||||
... //没有隐式转换函数
|
||||
};
|
||||
|
||||
Widget w1(10, true); // 使用小括号初始化,调用第一个构造函数
|
||||
@ -187,10 +187,10 @@ Widget w4{10, 5.0}; // 使用花括号初始化,现在调用第二个构
|
||||
````cpp
|
||||
class Widget {
|
||||
public:
|
||||
Widget(); //默认构造函数
|
||||
Widget(); //默认构造函数
|
||||
Widget(std::initializer_list<int> il); //std::initializer_list构造函数
|
||||
|
||||
... //没有隐式转换函数
|
||||
... //没有隐式转换函数
|
||||
};
|
||||
|
||||
Widget w1; //调用默认构造函数
|
||||
@ -242,8 +242,7 @@ doSomeWork<std::vector<int>>(10, 20);
|
||||
````
|
||||
如果`doSomeWork`创建`localObject`时使用的是小括号,`std::vector`就会包含10个元素。如果`doSomeWork`创建`localObject`时使用的是花括号,`std::vector`就会包含2个元素。哪个是正确的?`doSomeWork`的作者不知道,只有调用者知道。
|
||||
|
||||
这正是标准库函数`std::make_unique`和`std::make_shared`(参见[Item21](https://github.com/kelthuzadx/EffectiveModernCppChinese/blob/master/4.SmartPointers/item21.md))面对的问题。它们的解决方案是使用小括号,并被记录在文档中作为接口的一部分。(注:更灵活的设计——允许调用者决定从模板来的函数应该使用小括号还是花括号——是有可能的。详情参见[Andrzej’s C++
|
||||
blog](http://akrzemi1.wordpress.com/)在2013年6月5日的文章,“[Intuitive interface — Part I.](http://akrzemi1.wordpress.com/2013/06/05/intuitive-interface-part-i/)”)
|
||||
这正是标准库函数`std::make_unique`和`std::make_shared`(参见[Item21](https://github.com/kelthuzadx/EffectiveModernCppChinese/blob/master/4.SmartPointers/item21.md))面对的问题。它们的解决方案是使用小括号,并被记录在文档中作为接口的一部分。(注:更灵活的设计——允许调用者决定从模板来的函数应该使用小括号还是花括号——是有可能的。详情参见[Andrzej’s C++ blog](http://akrzemi1.wordpress.com/)在2013年6月5日的文章,“[Intuitive interface — Part I.](http://akrzemi1.wordpress.com/2013/06/05/intuitive-interface-part-i/)”)
|
||||
|
||||
**请记住:**
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user