【Effective Modern C++】第二章 auto:5. 优先使用 auto,而非显式类型声明

传统显示类型声明存在的问题

1. 忘记初始化产生未知行为

但是,auto声明的变量其类型推导自其初始化表达式,所以它们必须初始化:

c++ 复制代码
int x1; // 有潜在的未初始化风险 
auto x2; // 编译错误!必须有初始化表达式
auto x3 = 0; // 没问题, x 已经定义了

2. 类型冗长复杂,难以直接写出

在泛型编程、容器操作等场景中,尝尝会出现冗长复杂的类型声明。如:typename std::iterator_traits<It>::value_type,可以直接使用auto代替。

c++ 复制代码
// 传统显式声明:冗长繁琐,易出错 typename 
std::vector<int>::const_iterator it1 = vec.cbegin(); 

// auto 声明:简洁高效,无需记忆复杂类型 
auto it2 = vec.cbegin();

3. 类型不匹配导致意外的类型转换。

std::function是C++11标准库中的一个模板,它把函数指针的思想加以推广。函数指针只能指向函数,而std::function却可以指向任何可调用对象,即任何可以像函数一样实施调用之物。可以处理C++中的闭包类型。

但是,闭包类型只有编译器自己知道,显式声明闭包类型可能产生潜在的类型转换。如:

c++ 复制代码
std::unordered_map<std::string, int> m; 

// 看似合理,实则存在类型不匹配
for (const std::pair<std::string, int>& p: m) {
	... // 在p上实施某些操作
}

哈希表中的 std::pair (也就是 std::unordered_map 本身)的类型并不是 std::pair<std::string, int> ,而是 std:: pair<const std::string, int>

还可以避免一种被称作者为"类型捷径"的问题。如:

c++ 复制代码
std::vector<int> v; 
unsigned sz = v.size();

在 32 位 Windows 上, unsignedstd:: vector<int>::size_type 的尺寸是一样的,但在 64 位 Windows 上, unsigned 是 32 位,而 std:: vector<int>::size_type 则是 64 位。

其他优势

  • auto存储所需的内存可能比std::function更小,且调用效率更高(std::function采用类型擦除技术,存在间接调用开销,auto直接推导闭包原始类型,无额外损耗)。
  • 方便进行统一修改和重构,变量类型会随初始化表达式自动适配,修改源头类型时,无需手动调整所有相关变量,减少遗漏风险。
  • 支持匿名类型的直接使用,C++中的lambda表达式、匿名类均为编译器生成的匿名类型,无法手动显式声明,auto是唯一能直接存储这类对象的方式。

可能存在的问题:无法一眼看出对象的类型,但是IDE的对象类型显示能力能缓和这个问题,而且良好的命名比类型更能表达意图。

总结

  • auto变量必须初始化,基本上对会导致兼容性和效率问题的类型不匹配现象免疫,还可以简化重构流程,通常也比显式指定类型要少打一些字。
  • auto类型的变量都有着2. 理解 auto 类型推导和6中所描述的毛病。

原著在线阅读地址

相关推荐
玖釉-2 小时前
[Vulkan 学习之路] 26 - 图像视图与采样器 (Image View and Sampler)
c++·windows·图形渲染
一颗青果2 小时前
C++的锁 | RAII管理锁 | 死锁避免
java·开发语言·c++
AI视觉网奇2 小时前
ue c++ 编译常量
c++·学习·ue5
一分之二~2 小时前
回溯算法--解数独
开发语言·数据结构·c++·算法·leetcode
liu****2 小时前
第一章 Qt 概述
开发语言·c++·qt
休息一下接着来3 小时前
C++ 设计模式:Pimpl(Pointer to Implementation)
c++·算法·设计模式
苦藤新鸡3 小时前
18.矩阵同行同列全置零
数据结构·c++·算法·力扣
啟明起鸣4 小时前
【Linux 项目管理工具】GDB 调试是现成 C/C++ 项目的 “造影剂”,用来分析项目的架构原理
linux·c语言·c++
呼啦啦5614 小时前
【C++入门】
c++