C11新特性之decltype类型推

在前面一章,小编已经对auto类型推导这个关键字进行了介绍,相信小伙伴们都知道了auto的用法以及限制了吧,不知道的小伙伴回头自己去搜索一下~~~。

一、decltype关键字

在这一章节中,小编要告诉你另外一个关键字,这个关键字也是作为类型推导用的,它是C++11新特性新加的一个关键字。这个关键字就是decltype,它和auto的功能一样,也是在编译器编译时期进行自动类型的推导。其实你可以把这个关键字看成是declare和type的缩写,这样是不是显得更加明确了呢?

看到这里,你肯定有一个疑问就是,为什么有了auto类型推导,还要有decltype这个关键字的出现呢?其实细心一点的话你可以发现auto关键字有一些限制,也就是上章节有讲到的限制,像定义变量的时候一定要初始化,不能作用于类的非静态变量。所以我们总结了auto并不是适用于所有的自动类型推导的场景,在某些特定环境下auto使用起来非常的不方便,甚至无法使用它,所以C++11新特性才会引出decltype这个关键字。

我们都知道auto定义变量的语法为:

autoserven_1=10;

可以看到auto是根据=右边的初始值来自动推导变量的类型,所以auto在定义的时候必须初始化;而同样decltype也有自己的语法,它的语法为:

decltype(exp)varname=value;

其中,varname表示变量名,value表示赋值变量的值,exp表示一个表达式,这就是和auto最大的区别了,decltype是根据表达式exp来自动推导出变量的类型,跟=右边的value没有关系,所以decltype在定义的时候可以不用初始化,因此,decltype定义变量也可以写成:

decltype(exp)varname;

这里需要注意exp表达式,通常一说到表达式,我们脑子里面想到的就是一个普通的表达式,像x=1等等,但是关键字decltype关键字中的表达式可以是复杂的表达式,复杂到你怀疑人生嘿嘿嘿。但是有一点需要注意的是必须保证表达式exp的结果是有类型的,不能是void。像exp在调用一个返回值类型为void的函数时,exp的结果也是void类型,此时编译器会给你直接报错了。

voidshow(){cout"三贝勒文子!"endl;}decltype(show())serven_2;//编译器会一脸问号的问你,这是啥玩意???

如果使用下面的代码:

intshow(){cout"Serven"endl;return6;}intmain(){intserven_1=1;decltype(serven_1)serven_2=3;decltype(show())serven_3=5;coutserven_3endl;//会打印5,但是不会打印函数show中的内容}

decltype用法:

intserven_1=0;decltype(serven_1)serven_2=1;//serven_2被推导为intdecltype(1.2)serven_3;//serven_3被推导为double,不初始化也可以decltype(serven_3+)serven_4;//serven_4被推导为double

从上面的例子可以看到,decltype能够根据变量、字面量、带有运算符的表达式或者函数的返回类型推导出变量的类型。

二、decltype的推导规则

上面的例子让我们知道了decltype的一些初级用法,下面我们来了解一下decltype的高级用法吧,它的高级用法可以非常的复杂,当我们使用关键字来进行类型推导的时候,编译器有三个规则:

如果表达式exp是一个不被括号()包围的表达式,或者是个类成员访问表达式,或者是一个单独的变量,那么decltype(exp)的类型就是和exp一致的,这应该不难理解;

如果exp是函数调用,那么decltype(exp)的类型就和函数的返回值类型一致,但是注意一点就是函数的返回值不能是void;

如果exp是一个左值,或者被括号()包围,那么decltype(exp)的类型就是exp的引用,假如exp的类型为T,那么decltype(exp)的类型就是T。

1、表达式为单独变量

#includeQCoreApplication#includeiostream#includestringusingnamespacestd;classSERVEN_PAR{public:staticintser1;//类静态变量在类中不能初始化stringser2;intser3;floatser4;};intSERVEN_PAR::ser1=1;//初始化类的静态变量intmain(intargc,char*argv[]){QCoreApplicationa(argc,argv);intn=0;constintr=n;SERVEN_PARSERVEN;decltype(n)b=n;//n为int类型,b被推导为int类型decltype(r)c=n;//r为constint类型,c被推导为constint类型decltype(SERVEN_PAR::ser1)d=0;//ser1位类的一个int类型成员,那么d被推导为int类型decltype(SERVEN.ser2)e="


转载请注明:http://www.aierlanlan.com/tzrz/506.html

  • 上一篇文章:
  •   
  • 下一篇文章: