function8-auto/decltype
引用
c++ 11:
- auto->decltype
前言
auto是一种自动推导的类型,之前学过但是用的比较少。
主要也是c++不像java吧,java这种后端项目好像即使大版本更新了,项目也不会主动去换jdk。
c++稍微自由一点,听过的感觉都逐步靠近新版本,但肯定不是绝对,毕竟旧项目不考虑升级单纯维护的话也用不到那么新的。
auto好像还是c++11有的,c++14之后对auto又提供了什么也还不知道。
既然可以自动推导,那么可以用来定义变量或者函数
1 | auto a = 123; //等价与 int a = 123; auto定义的时候必须有初值,否则无法确定类型,无法确定类型也就无法确定大小。 |
但是这两种使用场景并不是auto最恰当的用法,不管是函数或者变量,其实不推荐auto去推导来声明
正文
自动推导的基础就是有关键信息,当信息不够的时候auto也无能为力。
同时auto肯定有缺点:
- auto不能保留const属性
1
2
3const int a{};
auto c = a;
//c只会是int,而非const - auto优先推导为值类型,而不是引用
1
2
3
4int a = 5;
const int &b = a;
auto c = a;
//c为int类型,而不是const& - auto利用返回值确定类型的时候会执行函数。
1
2auto x = ave(1,3);
//类型将由函数返回值而定
其实默认情况下还是需要自己推导的,不过最新的intellisense自动推导类型了
源代码应该是这样的没啥特殊:
1 |
|
intellisense自动推导后:
有好处也有坏处,好处自然省了推导,坏处就是自己不能推导了,虽然有点废话文学但是无关紧要你可以关掉。
当然前面也说了auto的缺点,所以我们指定类型:
1 | int& toMax(int &a, int &b){ |
传递是引用,返回也是引用,那么返回的引用就是谁大的结果。
实际调用的时候还能玩一收骚操作:toMax(a, b) = 500;
1 | int a = 150; |
找个样例测试一下:
有意思,发现b的值果然被修改了。
再回头想一想auto是否能这么做?
1 | auto toMax(int &a, int &b){ |
显然是不可以的,因为之前就说过,auto优先推断类型为值类型传递。
也就是先前截的图,auto的时候intellisense自动推导了类型是int类型的返回值,既然是int类型那么修改肯定就不合法了,因为返回的是一个值,而不是一个变量。
当然这样一搞,显得auto很呆,所以后面的标准又加入了新的讨论:拖尾函数
1 | auto toMax(int &a, int &b)->int&{ |
能看到编译器在形式上通过了这种写法。不过具体用处在这还体现不出来要等以后再看。
decltype
这玩意怎么说呢,通过一个表达式去获得类型,比如说:
1 | int a{}; |
如果表达式只是一个变量,那么推断类型就为该变量的类型。
减法是要看隐式转换的条件,或者说等级。
或许这样粗看感觉还不如auto
但是,decltype可以保留const和引用类型!
1 | int a{}; |
这简直就是哦买噶~
但是还有一种经历运算之后的操作:
1 | int a = 100; |
这样说可能有点绕,自己多敲几个看看得到的是什么类型的变量
然后还有一种比较简单的就是根据函数返回值来确定:
1 | int ave(int a,int b){ |
但是注意decltype不会执行函数,只会通过数据类型去猜,而auto是会去执行函数的
auto->decltype
已经知道decltype套函数的时候不会调用,而且decltype可以推导const和引用等类型
1 | auto toMax(int &a, int &b)->int&{ |
像这种直白的写法可以说拜拜!
1 | auto toMax(int &a, int &b)->decltype(a > b ? a : b){ |
根据这样的推导是求出了引用的类型,但是写法上好似有重复,又有点累赘。
所以在c++ 14以后引入了新的写法,上述的写法是基于c++11:
1 | decltype(auto) toMax(int &a, int &b){ |
这种写法就可以不使用拖尾函数了,但是编译器要支持c++14所以用这种写法要注意。
结语
自动推导感觉。。还是慎用吧,除非你很严谨,不然到时候找翻天了。







