C++11系列文章之一 | 类型推导神功修炼
大家好,我是小杰。
如果读完这篇感觉到有用的知识增加了,不妨点个赞、在看和关注,鼓励一下!
很抱歉最近两周我没怎么发原创,并不是我忘记了,而是遇到了考试周,五门考试真的是太忙了(毕竟没有听课),所以我断更了,接下来我会接着更下去。
这段时间我虽然没有更文,但是我也在思考着文章的方向,我打算出几个系列,每个系列出完之后会出一篇汇总文章方便读者收藏和学习,当然我也会放到公众号下面的按钮中方便找到,目前想到的有网络框架的源码解析系列、XX天从零开发网络框架系列、C++11、14、17等系列及其应用、STL源码解析系列、Linux源码刨析系列、Go语言的入门到源码系列、包括计算机操作系统,计算机网络、数据结构等系列,这是我目前想到的,后续会有其他系列我会接着更,尽请期待!我会一直做下去!
auto类型推导
C++旧标准:
具有自动存储的局部变量
auto int i = 0 //C++98
实际上我们一般不这样写,因为非static变量默认就是具有自动存储的局部变量
C++11:
让编译器自动推断出这个变量的类型,而不需要显式指定类型
auto基本用法
演示:
auto x = 5//x --> intauto pi = new auto(1)//pi --> int*const auto *v = &x, u = 6//v --> const int* 、 u --> const intstatic auto y = 0.0//y --> doubleint x = 0 auto * a = &x //a --> int* , auto为intauto b = &x //b --> int* , auto 为 int*autoc = x//c --> int& , auto为intauto d = c //d --> int , auto为intconst auto e = x//e--> const intauto f = e//f --> intconst auto& g = x//g --> const int&auto& h = g//h --> const int&
上面就是通常会出现的所有情况,其实可以类比模板参数自动推导
auto 不能用于函数参数
auto 推导规则
黄金法则:
- 当不声明为指针或引用时,auto的推到结果和初始化表达式抛弃引用和cv限定符(cosnt 和 volatile,下同)后类型一致
- 当声明为指针或引用时,auto的推到结果将保持初始化表达式的cv属性
auto 的限制
- 不能用于函数参数
- 不支持非静态成员变量的初始化
- main函数中auto不会被推导为数组类型,而是指针类型
auto 适用场景
场景一:
for循环中用来遍历容器
for(auto it = resultMap.begin(); it != resultMap.end(); ++i){ //do something}
场景二:
用于不知道如何定义变量,多与泛型有关
class Foo{ public: static int get(void) { return 0; }};class Bar{ public: static const char* get(void) { return "0"; }};templatevoid func(void) { auto val = A::get(); // ...}
decltype 类型推导
decltype( exp )
exp 表示一个表达式
从格式上来看,decltype像sizeof ,但其用来在编译时推导出一个表达式的类型
decltype 基本用法
int x = 0decltype(x) y = 1//y -> intdecltype(x + y) z = 0//z -> intconst int& i = xdecltype(i) j = y//j -> const int &cosnt decltype(z) *p = &z//*p -> const int, p -> const int *decltype(z) * pi = &z//*pi -> int , pi -> int*decltype(pi) * pp = &pi//*pp -> int * ,pp -> int
decltype和&结合的推导结果,与引用折叠规则有关,将在本系列后续中详细讲解
decltype 推导规则
黄金法则:
- exp是标识符、类访问表达式,decltype(exp) 和exp的类型一致
- exp是寒素调用,decltype(exp) 和返回值 的类型一致
- 其他情况,若exp是个左值,则 ecltype(exp) 是exp类型的左值引用,否则和exp类型一致
decltype 适用场景
decltype适用于泛型相关
场景一:
标准库中有些类型的定义
typedef decltype(nullptr) nullptr_ttypedef decltype(sizeof(0)) size_t
场景二:
通过变量表达式抽取变量类型实现简写
vector v;decltype(v):value_type i = 0
场景三:
templateclass Foo{ decltype(ContainerT().begin()) it_;public: void func(ContarinerT& container) { it_ = container.begin(); } // ...}
auto 和 decltype结合——返回类型后置
即通过两个结合起来,使得语法更加灵活便捷
int & foo(int& i);float foo(float& f)template auto fun(T& val) -> decltype(foo(val)) { return foo(val);}
小结
auto和decltype的出现不仅弥补了C++旧版标准的不足,也大大解放了开发人员的生产力,提升了效率。但是我们在使用的时候仍然需要注意,不能滥用,否则会出现我们期望得到的类型和最终程序的类型不一致,导致一些意想不到的BUG,给我维护增加了成本,适用和巧用才是正解!