decltype类型声明

有时会遇到这样的情况:希望从表达式的类型推断出要定义的变量的类型,但不想用该表达式的值去初始化变量。为了满足这一需求,C++11引入了decltype,它的作用是选择并返回操作数的数据类型。在此过程中,编译器分析表达式并得到它的类型,却不实际计算表达式的值。

decltype(f()) sum = x;	//sum的类型就是函数f的返回类型,编译器并不实际调用函数f。

再者,decltype比较典型的用法就是与typedef/using的合用。在C++11的头文件中,我们常能看到以下的代码:

using size_t = decltype(sizeof(0));
using ptrdiff_t = decltype((int*)0 - (int*)0);
using nullptr_t = decltype(nullptr);

这种定义方式非常有意思,在一些常量、基本类型、运算符、操作符等都已经被定义好的情况下,类型可以按照规则被推导出。而使用using,就可以为这些类型取名。这就颠覆了之前类型拓展需要将拓展类型“映射”到基本类型的常规做法。

跟auto一样,由于应用广泛,所以使用decltype也有很多的细则条款需要注意。

当利用decltype(e)来获取类型时,编译器将依序判断以下四规则:

1)如果e是一个没有带括号的标记符表达式(id-expression)或者类成员访问表达式,那么decltype(e)就是e所命名的实体的类型。此外,如果e是一个被重载的函数,则会导致编译时错误。

如果参数是任何其他类型为T的表达式,且

2)如果e是一个亡值(xvalue),那么decltype(e)为T&&。

3)如果e是一个左值,则decltype(e)为T&。

4)如果e是一个纯右值,则decltype(e)为T。

这里需要解释下标记符表达式(id-expression)。基本上,所有除去关键字、字面量等编译器需要使用的标记之外的程序员自定义的标记(token)都可以是标记符(identifier)。而单个标记符对应的表达式就是标记符表达式。比如程序员定义了:

int arr[4];

那么arr是一个标记符表达式,而arr[3]+0,arr[3]等,则都不是标记符表达式。

上面的规则看起来复杂,但事实上,在实际应用中,最容易引起迷惑的只有规则1和3。可以通过下面的代码清单来加深下理解。

int i = 4;
int arr[5] = { 0 };
int *ptr = arr; struct S
{
double d;
}s; void Overloaded(int); //重载的函数 int && RvalRef(); //规则1:单个标记符表达式及访问类成员,推导为本类型
decltype(i) var0; //标记符表达式
decltype(arr) var1; //int[5],标记符表达式
decltype(ptr) var2; //int *,标记符表达式
decltype(s.d) var4; //double,成员访问表达式
decltype(ptr) var2; //无法编译,是个重载函数 //规则2:亡值推导为类型的右值引用
decltype(RvalRef()) var6 = 1; //int&& //规则3:左值推导为类型的引用
decltype((i)) var8 = i; //int&, 带圆括号的左值
decltype(arr[3]) var10 = i; //int&, []操作返回左值
decltype(*ptr) var11 = i; //int&,*操作返回左值 //规则4:纯右值,推导为本类型
decltype(1) var13; //int,除字符串外字面常量为右值

需要注意规则3例子中(i)不是一个标记符表达式,但却是一个左值表达式,(可以有具名的地址),

因此按照规则3,其类型是一个int的引用。这是与auto的一处重要区别————decltype的结果类型与表达式形式相关。

此外,decltype处理顶层const,和引用的方式与auto有些不同。如果decltype使用的表达式是一个变量,则decltype返回该变量的类型(包括顶层const和引用在内),而auto中会忽略掉顶层const和引用。

int i = 0;
const int ci = i, &cr = ci;
decltype(ci) b = 0; //b:const int
decltype(cr) c = b; //c:const int &,因为cr就是引用类型

decltype类型声明- 现代C++新特性总结的更多相关文章

  1. Java基础知识强化66:基本类型包装类之JDK5新特性自动装箱和拆箱

    1. JDK1.5以后,简化了定义方式. (1)Integer  x = new  Integer(4):可以直接写成如下:         Integer  x = 4 ://自动装箱,通过valu ...

  2. C# 9.0 新特性预览 - 类型推导的 new

    C# 9.0 新特性预览 - 类型推导的 new 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大 ...

  3. 【C++基础学习】类型声明

    1.初始化 在C++中,初始化与赋值操作是完全不同的两个操作.初始化不是赋值,初始化的含义是创建变量时赋予其一个初始值,而赋值的含义是把对象的当前值擦除,而以一个新值来代替. 初始化的方式有: 1 i ...

  4. C# 9.0 新特性预览 - 顶级语句

    C# 9.0 新特性预览 - 顶级语句 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大家展示它们 ...

  5. java7与java8的新特性

    java7 新特性: 1. switch 里面的 case 条件可以使用字符串了. 2. 运用 List\tempList = new ArrayList<>(); 即泛型实例化类型自动判 ...

  6. C# 9.0 新特性预览 - 空参数校验

    C# 9.0 新特性预览 - 空参数校验 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大家展示它 ...

  7. C# 9.0 新特性预览 - init-only 属性

    C# 9.0 新特性预览 - init-only 属性 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章 ...

  8. C++11新特性— auto 和 decltype 区别和联系

    一. auto简介 编程时候常常需要把表达式的值付给变量,需要在声明变量的时候清楚的知道变量是什么类型.然而做到这一点并非那么容易(特别是模板中),有时候根本做不到.为了解决这个问题,C++11新标准 ...

  9. Java 8 新特性之泛型的类型推导

    1. 泛型究竟是什么? 在讨论类型推导(type inference)之前,必须回顾一下什么是泛型(Generic).泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据 ...

随机推荐

  1. Struts2(二)工作原理

    一.概述 1.struts框架本身分为三个部分:核心控制器FilterDispatcher.业务控制器Action和用户实现的企业业务逻辑组件. 2.struts2工作的基本流程: 客户端初始化一个指 ...

  2. PHP 中文字符串截取

    $str = "abcdef啊啊吧啊"; function my_sub($str, $st ,$len){ $ret = ""; for( $st; $len ...

  3. 【WEB前端开发最佳实践系列】高可读的HTML

    一.HTML语义化 HTML5中增加了很多标签都是基于此类原则设计的(article   nav  header  footer).页面标签语义化的优点是使得搜索引擎以及第三方抓包工具等更容易读懂页面 ...

  4. Android MediaScanner

    一.MediaScanner 的使用 1)Intent.ACTION_MEDIA_SCANNER_SCAN_FILE:扫描指定文件 public void scanFileAsync(Context ...

  5. 【CF883B】Berland Army 拓扑排序

    [CF883B]Berland Army 题意:给出n个点,m条有向边,有的点的点权已知,其余的未知,点权都在1-k中.先希望你确定出所有点的点权,满足: 对于所有边a->b,a的点权>b ...

  6. iOS - 引用计数探讨

    <Objective-C 高级编程> 这本书有三个章节,我针对每一章节进行总结并加上适当的扩展分享给大家.可以从下面这张图来看一下这三篇的整体结构: 注意,这个结构并不和书中的结构一致,而 ...

  7. MUI---IOS切换到后台继续播放音乐

    应用切换到后台继续音乐播放HBuilder默认生成的应用在iOS是不支持后台音乐播放的,当应用切换到后台时音乐将暂停播放,下次切换到前台继续播放.如果要支持应用切换到后台后继续播放音乐功能需要进行额外 ...

  8. 算法学习之快速排序的C语言实现

    近几天在学习简单算法,今天看了一个快速排序和堆排序,堆排序还没搞懂,还是先把快速排序搞清楚吧 教程网上一艘一大堆,这里选择一个讲的比较通俗的的一个吧: http://blog.csdn.net/mor ...

  9. 基于pandas python的美团某商家的评论销售(数据分析)

    数据初步的分析 本文是该系列的第一篇 数据清洗 数据初步的统计 第二篇 数据可视化 第三篇 数据中的评论数据用于自然语言处理 from pyecharts import Bar,Pie import ...

  10. POJ 3067 - Japan - [归并排序/树状数组(BIT)求逆序对]

    Time Limit: 1000MS Memory Limit: 65536K Description Japan plans to welcome the ACM ICPC World Finals ...