【Effective Modern C++】第二章 auto:6. 当auto推导的类型不符合要求时,使用显式类型初始化习惯用法

个人认为原著写的非常难懂,所以精简总结如下:

auto与代理类的问题:

当使用auto进行类型推导时,如果表达式返回的是代理类,auto会推导出代理类型而不是被代理的实际类型,可能导致未定义行为。

例如:

c++ 复制代码
std::vector<bool> features(const Widget& w);
bool highPriority = features(w)[5];  // 含义是w具有高优先级吗?
processWidget(w, highPriority);      // 按照w的优先级来处理

这段代码没有什么问题,但是如果把highPriority从显式类型改成auto

c++ 复制代码
auto highPriority = features(w)[5];  // 危险!推导出std::vector<bool>::reference
processWidget(w, highPriority);      // 可能产生未定义行为!

原因:

  1. std::vector<bool>内部使用紧凑结构存储(每个bool占1位)
  2. 内存最小寻址单位是字节,单个 "位" 没有独立的内存地址;
  3. operator[]无法返回bool&(不能对单个位取引用),因此返回一个代理类std::vector<bool>::reference
  4. auto不会自动把代理类转换成bool,而是直接推导成std::vector<bool>::reference类型。

因此需要显式声明 其为bool类型:

c++ 复制代码
auto highPriority = static_cast<bool>(features(w)[5]);  // 安全!

如何识别出代理类

头函数或函数签名会反映出其存在:

c++ 复制代码
namespace std {
    template<class Allocator>
    class vector<bool, Allocator> {
    public:
        class reference { ... };  // 代理类!
        reference operator[](size_type n);
        ...
    };
}

非同寻常的返回值类型:如:std::vector<T>::operator[]通常返回T&,如果返回类型不是T&,可能是代理类。

常见的代理类场景:

  • std::vector<bool>的相关操作:位无独立地址,无法返回引用。
  • 表达式模板(用于优化数值计算):临时对象多,计算效率低。
  • 某些智能指针的实现:内存访问不安全/权限难控。
  • 延迟求值(lazy evaluation)系统:提前计算可能无效。

其他应用场景

1. 精度控制

c++ 复制代码
double calcEpsilon();
auto ep = static_cast<float>(calcEpsilon());  // 明确表示精度降低

还可以应用于计算随机访问迭代器的容器中的某个元素下标。

2. 类型转换强调

c++ 复制代码
double d = 0.7;
size_t size = 100;
auto index = static_cast<int>(d * size);  // 明确表示浮点到整数的转换

3. 表达式模板的代理

c++ 复制代码
Matrix m1, m2, m3, m4;
auto sum = static_cast<Matrix>(m1 + m2 + m3 + m4);  // 避免代理类型

总结

  • "隐形"的代理类型可以导致auto根据初始化表达式推导出"错误的"类型。
  • 带显式类型的初始化习惯用法强制auto推导出你想要的类型。

原著阅读地址

相关推荐
智者知已应修善业13 小时前
【51单片机模拟生日蜡烛】2023-10-10
c++·经验分享·笔记·算法·51单片机
智者知已应修善业13 小时前
【51单片机如何让LED灯从一亮到八,再从八亮到一】2023-10-13
c++·经验分享·笔记·算法·51单片机
qeen8713 小时前
【数据结构】二叉树相关经典函数C语言实现
c语言·数据结构·c++·笔记·学习·算法·二叉树
良木生香13 小时前
【C++初阶】STL——List从入门到应用完全指南(1)
开发语言·数据结构·c++·程序人生·算法·蓝桥杯·学习方法
aqiu11111114 小时前
【并查集专题top】
c++·算法
会周易的程序员14 小时前
aiDgeScanner 工业设备网络扫描与管理工具
网络·c++·物联网·架构·electron·node.js·iot
叼烟扛炮14 小时前
C++ 知识点17 友元
开发语言·c++·算法·友员
计算机安禾14 小时前
【c++面向对象编程】第2篇:类与对象(一):定义第一个类——成员变量与成员函数
开发语言·c++
richard_yuu14 小时前
数据结构|二叉树高阶进阶-经典算法
数据结构·c++·算法