《Effective Modern C++》学习笔记 - Item 2: 理解auto类型推导
2021/12/15 14:20:56
本文主要是介绍《Effective Modern C++》学习笔记 - Item 2: 理解auto类型推导,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
- 除了一种特殊情况外,
auto
类型推导就是模板类型推导(尽管二者在形式上看起来不同) - 当变量用
auto
声明时,auto
取代了模板中T
的角色,而变量的类型等同于ParamType
。下面的例子展示了二者的等价性:
auto x = 27; // 等价于以下模板推导 template<typename T> // 推导x类型的假想模板,下同 void func_for_x(T param); func_for_x(27); const auto cx = x; // 等价于以下模板推导 template<typename T> void func_for_cx(const T param); func_for_cx(x); const auto& rx = x; // 等价于以下模板推导 template<typename T> void func_for_rx(const T& param); func_for_rx(x);
- 类似于模板推导的三种情况:
- Case 1: 类型标识符(type specifier)是指针或引用,但不是万能引用。
- Case 2:类型标识符是万能引用。
- Case 3: 类型标识符既不是指针也不是引用
- 上面的例子已经展示了Case 1和3,Case 2的运作方式也如预期:
auto&& uref1 = x; // x是左值int,所以uref1是int& auto&& uref2 = cx; // cx是左值const int,所以uref2是const int& auto&& uref3 = 27; // 27是右值int,所以uref3是int&&
- 对数组和函数的讨论也对
auto
成立:
const char name[] = "hello"; auto arr1 = name; // arr1是const char* auto& arr2 = name; // arr2是const char (&)[13] void someFunc(int, double); auto func1 = someFunc; // func1是void (*)(int, double) auto& func2 = someFunc; // func2是void (&)(int, double)
- 二者只在一个方面不同。C++11引入了统一初始化(uniform initialization),以下四种初始化方式的结果是一样的:
// 都将x初始化为int值27 int x1 = 27; int x2(27); int x3 = { 27 }; int x4{ 27 };
但如果直接将标识符改为 auto
,这些声明仍都能通过编译,但意思不同。前两个仍声明一个值为27的 int
,但后两个声明的是包含一个元素27的 std::initializer_list<int>
!
auto x1 = 27; // 类型为int,值为27 auto x2(27); // 同上 auto x3 = { 27 }; // 类型为std::initializer_list<int>, 值为 { 27 } auto x4{ 27 }; // 同上
这是由于 auto
类型推导的一条特殊规则:当使用大括号包围的初始化器(initializer)对一个 auto
描述的变量进行初始化时,推导出的类型是 std::initializer_list
。如果推导不出这样的类型(如大括号包围的初始化器中有多个不同类型的元素)时,代码会编译报错。
要理解这里其实是一个两步的推导过程:由于 x
使用 大括号初始化,首先要推导出 x
是 std::initializer_list<T>
,而后者又是一个模板,所以要从初始化列表中推出 T
的类型。
以上适用于 auto
的规则并不适用于模板推导,例如以下代码会报错:
template<typename T> void f(T param); f({ 11, 23, 9 }); // error!
解决方法为:
template<typename T> void f(std::initializer_list<T> initList); f({ 11, 23, 9 });
- C++14还允许使用
auto
推导函数返回值,以及在lambda函数中使用auto
声明参数。然而auto
的这些使用遵循的是模板类型推导的规则,而不是auto
类型推导的规则,所以以下代码均会报错:
auto createInitList() { return { 1, 2, 3 }; // error } std::vector<int> v; auto resetV = [&v](const auto& newValue) { v = newValue; }; // C++14 resetV({ 1, 2, 3 }); // error
总结
auto
类型推导通常与模板类型推导相同,但auto
类型推导将大括号包裹的初始化器(initializer)识别为std::initializer_list
,而模板类型推导不会。auto
在函数返回值类型或lambda函数参数中遵循模板类型推导规则,而不是auto
类型推导的规则。
这篇关于《Effective Modern C++》学习笔记 - Item 2: 理解auto类型推导的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-24怎么切换 Git 项目的远程仓库地址?-icode9专业技术文章分享
- 2024-12-24怎么更改 Git 远程仓库的名称?-icode9专业技术文章分享
- 2024-12-24更改 Git 本地分支关联的远程分支是什么命令?-icode9专业技术文章分享
- 2024-12-24uniapp 连接之后会被立马断开是什么原因?-icode9专业技术文章分享
- 2024-12-24cdn 路径可以指定规则映射吗?-icode9专业技术文章分享
- 2024-12-24CAP:Serverless?+AI?让应用开发更简单
- 2024-12-23新能源车企如何通过CRM工具优化客户关系管理,增强客户忠诚度与品牌影响力
- 2024-12-23原创tauri2.1+vite6.0+rust+arco客户端os平台系统|tauri2+rust桌面os管理
- 2024-12-23DevExpress 怎么实现右键菜单(Context Menu)显示中文?-icode9专业技术文章分享
- 2024-12-22怎么通过控制台去看我的页面渲染的内容在哪个文件中呢-icode9专业技术文章分享