decltype函数_decltype有什么用

decltype函数_decltype有什么用前言如果想要知道一个表达式的数据类型但又不想对表达式进行求值,那么auto似乎就不满足这中要求,c++11加入了decltype操作符,它的功能与auto类似,都是进行类型推导,但是decltype就能对某一表达式的类型进行推导并且不求表达式的值.因为decltype在很多的时候并不同于auto操作符,所以我会将大部分的不同罗列出来,比如:数组,顶层const等.declt…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

前言

如果想要知道一个表达式的数据类型但又不想对表达式进行求值, 那么auto似乎就不满足这中要求, c++11加入了decltype操作符,它的功能与auto类似, 都是进行类型推导, 但是decltype就能对某一表达式的类型进行推导并且不求表达式的值.

因为decltype在很多的时候并不同于auto操作符, 所以我会将大部分的不同罗列出来, 比如 : 数组, 顶层const等.

decltype

decltype的声明 :

decltype(exp()) x; 	// exp()可以是任何的表达式

1. decltype与普通类型

先来看看怎么使用decltype操作符

int i = 0;
decltype(i) di;	// 需要传入一个表达式才行, di并不必须要初始化
decltype(i + 0) j;
decltype(function()) f;

auto ai = i;	// auto必须对其进行初始化

auto不同, decltype根据表达式就能推导出类型, 所以不需要必须对创建的变量进行初始化, 而auto是需要根据右值的类型进行推导出左值的参数类型, 所以必须在创建的时候进行初始化.

2. decltype与数组

decltype推导数组类型的时, 推导的并不是指针类型, 而是数组类型.

int a[10]{ 
   0};
decltype(a) da; 	// 这里推导的da是一个 int[10] 类型的数组, 不是指针
decltype(a + 1) pa;	// 这里推导的da是指针
auto pa = a;		// auto推导的pa是一个指针
pa = &a[0];	// success, 因为pa是指针
da = &a[0];	// error. da类型是 int[10], 不是指针

decltype推导类型就一定要注意, 以上的例子可能以后些代码就会遇到的问题. 同时可以看出来autodecltype多做了一层转换, 将数组转换成了指针.

3. decltype与顶层const

在分析顶层const时分析过, auto会忽略掉顶层const, 即

const int cc = 0;
auto a = cc; 	// auto忽略了顶层const, 所以a的其实只是int类型

而**decltype在推导时并不会忽略顶层const**

const int cc = 0;
decltype(cc) dc = 1;	// 必须对dc进行初始化, 因为dc是const int类型

这里也就可以看出来decltype很”老实”, 给我什么类型就返回什么类型, 而auto很”聪明”, 知道做一些转换.

4. decltype与引用

引用也是一样, auto会将引用忽略掉, 而decltype则会保留引用. 即

int j = 0; int &reference_j = j;
decltype(reference_j) dj = j;	// 必须进行初始化, 因为dj是引用类型, 并不是int类型
auto aj = reference_j; aj = 1;	// success, auto会忽略掉引用, aj只是一个int类型

关于引用decltype还没有完, 因为不注意可能在使用decltype就会出问题.

int i = 0;
decltype((i)) j;	// error

我们在decltype中加上了一个(), 导致的结果就不一样了, 这里的 j 必须进行绑定, 因为他是引用.

记住 : decltype((variable)), 有双括号时结果永远都是引用.

5. decltype与表达式求值结果

本来是想将这个放在引用中来讲, 但是还是抽离出来, 不然可能会混淆的.

如果decltype中传入的不是一个表达式, 而是一个表达式求值的结果是一个左值, 则推导出来的类型是引用. 就如 : decltype(i = 0)返回的是引用. (需要解释一下 : 在c中 i=0这样的表达式返回的结果是一个右值, 而在c++中i=0返回的是一个左值. 可以通过(i=j)++进行验证, c中会报错, c++会正常运行.)

int i;
decltype(i = 0) j = i;	// j必须绑定, 因为decltype推导出来的是引用

同样, 指针解引用返回的也是左值, 所以

int a[] = { 
   1, 2};
decltype(*a) b = i;	// decltype推导出来的是引用, 因为*a表达式的结果是一个左值
decltype(&a[0]) ptr;	// decltype推导出的类型是 int **

6. decltype与模板

在模板中, 编译器能自行推导出传入函数的参数类型, 但是无法推导出返回值的类型, 这时我们就可以用decltype来解决这个问题.

template<typename T1, typename T2>
T2 func(T1 t1) { 
    return t1 + t1;}	// error. T2的类型无法推导出来

template<typename T1, typename T2>
auto func(T1 t1) -> decltype(t1+t2)	// success, 返回值的类型可以通过decltype推导出来
{ 
    return t1 + t1;}	

这里auto放在函数前面只是一个返回类型的占位符, 并不是auto来推导返回值类型, 而是decltype在函数返回的时候来推导返回值的类型

在c14中decltype也有所修改, 在返回值后置中做了一些修改, 可以不用后置, 使用可以如下 :

template<typename T1, typename T2>
decltype(auto) func(T1 t1) 	// success, 返回值的类型可以通过decltype推导出来
{ 
    return t1 + t1;}	

总结

本节罗列出了decltype的使用方法以及使用时的注意点, 这里做一个总体的归纳

  1. decltype通过表达式推导出来的是表达式的类型 (即decltype(variable) )
  2. 表达式求值的结果是左值, 则推导出来的是表达式的类型的引用 (即 decltype(variable = 0))
  3. 表达式是引用, 则推导出来的是引用 (即 decltype(reference) )
  4. 表达式加了括号的, 则推导出来的是表达式的类型的引用 (即 decltype((variable)) )
  5. 表达式是数组的首地址, 则推导出来的是数组类型 (即 decltype(arrary) )
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/195741.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • docker启动mysql命令_docker部署java环境

    docker启动mysql命令_docker部署java环境Docker启动Mysql一、单机版Mysql1、拉取官方镜像,镜像地址:/mysql/”>https://hub.docker.com//mysql/2、拉取镜像:dockerpullmysql3、准备Mysql数据存放目录,我这里是:/home/ljaer/mysql4、执行指令启动Mysqldocker@default:~$dockerrun–namemysql-v/home/ljaer/mysql:/var/lib/mysql-p3306:3

    2022年10月6日
    1
  • tcpdump抓包命令_tcpdump指定ip抓包命令

    tcpdump抓包命令_tcpdump指定ip抓包命令tcpdump是一个功能强大的命令行数据包分析器,它是通过监听服务器的网卡来获取数据包,所有通过网络访问的数据包都能获取到。它也提供了过滤器的功能,可以获取指定的网络、端口或协议的数据包程序员日常排查问题,最常用的是使用过滤器功能获取指定端口的数据包,用来分析服务器是否收到请求、请求数据是否完整。参数介绍tcpdump命令的参数很多,详见如下这里只介绍一些常用的参数​-ccount//count表示数量。抓取数据包的数量达到count后结束命令,如果不使用…

    2022年8月21日
    58
  • python 微信自动回复机器人

    python 微信自动回复机器人python微信自动回复机器人导入wxautohttps://github.com/cluic/wxauto#!python3#-*-coding:utf-8-*-“””Author:tikic@qq.comSource:https://github.com/cluic/wxautoLicense:MITLicenseVersion:3.3.5.3″””fromtokenizeimportNamefromunicodedataimportnameim

    2022年10月1日
    4
  • 微信小程序和php交互_php接收json数据

    微信小程序和php交互_php接收json数据微信js源码Page({onLoad:function(){varthat=thiswx.request({//要交互页面的地址url:’http://localhost/php/index.php/Wxwater/Test/test’,data:{pid:1//data里边使我们要传递给PH…

    2025年12月12日
    3
  • Ubuntu命令卸载软件「建议收藏」

    Ubuntu命令卸载软件「建议收藏」1.打开一个终端,输入dpkg–list,按下Enter键,终端输出以下内容,显示的是你电脑上安装的所有软件。2.在终端中找到你需要卸载的软件的名称,列表是按照首字母排序的。3.在终端上输入命令sudoapt-get–purgeremove包名(–purge是可选项,写上这个属性是将软件及其配置文件一并删除,如不需要删除配置文件,可执行sudoapt-getr…

    2022年5月30日
    38
  • Ubuntu命令行下树莓派连接WiFi操作方法

    Ubuntu命令行下树莓派连接WiFi操作方法第一种方法:通过配置/etc/network/interfaces文件实现终端输入sudovim/etc/network/interfaces修改后文件内容如下:autoloifaceloinetloopbackifaceeth0inetdhcpautowlan0allow-hotplugwlan0ifacewlan0inetdhcpwpa-ssid”你的wifi名称”wpa-p

    2022年6月10日
    65

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号