自动和静态类型转换——很好的实践
auto and static_casts - good practice
在Scott Meyer的《Effective Modern c++》一书中,我们可以读到:
std::vector<bool> features(const Widget& w);
Widget w;
…
bool highPriority = features(w)[5];
…
processWidget(w, highPriority);
和auto
选项auto highPriority = features(w)[5];
导致未定义的行为,因为features()
返回std::vector<bool>
,当从opearator[]
返回值时使用std::vector<bool>::reference
类型的代理对象。
作为一个解决方案,建议不要停止使用auto
,而是使用static_casts
。
所以Scott Meyers建议使用:
auto highPriority = static_cast<bool>(features(w)[5]);
代替:
bool highPriority = features(w)[5];
我的问题是:这两者的真正区别是什么?在我看来,这两种方法是相同的,因为这两种方法都以完全相同的方式使重构变得更加困难(改变函数特性中的返回值类型并不会使变量highPriority成为不同的类型),而且第二种方法更短。
如果您不喜欢features
的界面,您可以将其隐藏在辅助函数中
bool is_high_priority(const Widget& w)
{ return features(w)[5]; }
和现在的
auto highPriority = is_high_priority(w);
如果features
是一个返回std::vector<bool>
的函数,
auto highPriority = features(w)[5];
存储逻辑引用。存储对象指向一个不再存在的向量。使用它会导致未定义行为。
而不是做
bool const highPriority = features(w)[5];
或
auto const highPriority = !!features(w)[5];
或者Scott推荐的–但对我的口味来说太啰嗦了。使用static_cast
.
存储的对象现在是bool
。
这三种表达同一声明的方式在功能上没有区别。唯一的区别是非功能性的:在我看来,static_cast
不必要的冗长,!!
可能会抑制来自一个通用编译器的关于性能的愚蠢警告。
当您使用auto时,auto将其推断为highPriority返回的类型,highPriority是对bool的引用。问题是,highPriority返回的不是bool对象的引用,而是std::vector::引用对象。('reference'是std::vector中的嵌套类)。Std::vector::reference是一个"代理类",一个模仿其他类型行为的类。它不仅是一个代理类,而且是一个"不可见"的代理类。这样的类不能很好地与auto一起工作。Auto不能正确地推断不可见代理类的类型。但是static_cast强制将高优先级转换为bool类型。这避免了未定义行为。
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++中的双指针类型转换
- 逐位操作的隐式类型转换
- 模板中的类型转换
- 在 C++(和 C)中进行类型转换时明显不一致
- 字符类型转换不兼容
- 我编写了代码将十进制分数转换为其二进制等效数.它编译得很好,但在执行时挂起
- 为什么不同类型层次结构的指针之间的dynamic_cast定义得很好?
- 引用的静态强制转换强制模板实例化,其中不完整的类型很好
- 是否很好地定义了强制转换为仅由 char[] 组成的结构并从该数组读取?
- 有没有一种很好的方法来实现具有默认失败情况的条件类型?
- 支持按值传递语句的示例不是很好的做法,即使对于小型用户定义类型也是如此
- 类型转换C++的行为方式很奇怪
- 如何正确地对数据开始指针进行类型转换(这是一种很好的做法吗)
- 强制转换操作符函数在g++中可以很好地编译,但在其他编译器中不行.为什么
- 自动和静态类型转换——很好的实践
- 很好的哈希函数对基本类型
- 为什么decltype返回类型在递归模板中失败,而返回类型演绎却工作得很好?
- MultiByteToWideChar不能很好地转换我的字符串