• 【C++深陷】之“decltype”


    0. decltype关键字
    decltype被称作类型说明符,它的作用是选择并返回操作数的数据类型。

    // sum的类型就是函数f返回的类型
    decltype(f()) sum = x;
    1
    2
    回想【C++深陷】之“类型与变量”第4节,我们将定义变量的方法规范为:

    类型说明符 声名符列表
    1
    decltype就是一种类型说明符,它的出现主要是解决复杂的类型声明。

    随着程序越来越复杂,程序中用到的类型也越来越多,这种复杂性体现在两个方面。

    一是一些类型难于“拼写”,它们的名字既难记又容易写错,还无法明确体现其真实目的和含义。

    二是有时候根本搞不清到底需要的类型是什么,程序员不得不回过头去从程序的上下文寻求帮助。

    解决问题一,可以使用类型别名技术。

    解决问题二,可以使用auto和本文的主题:decltype。

    关于decltype,需要注意:

    工作原理
    decltype + 变量 var
    decltype + 表达式 expr
    decltype + 函数名 func_name
    1. 工作原理
    decltype并不会实际计算表达式的值,编译器分析表达式并得到它的类型。

    函数调用也算一种表达式,因此不必担心在使用decltype时真正的执行了函数,正如前例中的f()。

    2. decltype + 变量
    根据【C++深陷】之“表达式与运算符”中关于表达式的定义,我们知道单独使用一个变量,相当于一个最简单的表达式。

    但是在decltype这里有区别。

    ①当使用decltype(var)的形式时,decltype会直接返回变量的类型(包括顶层const和引用),不会返回变量作为表达式的类型。

    const int ci = 0, &cj = ci;

    // x的类型是const int
    decltype(ci) x = 0;

    // y的类型是const int &
    decltype(cj) y = x;
    1
    2
    3
    4
    5
    6
    7
    decltype加指针也会返回指针的类型。

    decltype加数组,不负责把数组转换成对应的指针,所以其结果仍然是个数组(P206)。

    总之decltype(var)完美保留了变量的类型。

    “变量作为表达式的类型”是什么呢?见下节。

    3. decltype + 表达式
    ②当使用decltype(expr)的形式时,decltype会返回表达式结果对应的类型。

    回想【C++深陷】之“表达式与运算符”,一个表达式的结果不是左值,就是右值。

    关于左值和右值,请参考【C++深陷】之“左值与右值”。

    因此,decltype(expr)的结果根据expr的结果不同而不同:expr返回左值,得到该类型的左值引用;expr返回右值,得到该类型。

    int i = 42, *p = &i, &r = i;

    // r + 0是一个表达式
    // 算术表达式返回右值
    // b是一个int类型
    decltype(r + 0) b;

    // c是一个int &
    decltype(*p) c = i;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    这里注意一下decltype(*p)。

    解引用运算符*作用于指针类型,得到了p指向的对象的左值(*p = 2很正确),p是指向int的指针,因此decltype(*p)得到的类型是int &。

    再来看第2节说到的“变量作为表达式的类型”。

    当变量作为表达式时,返回的是该变量的一个左值形式(因为该表达式的结果可以作为赋值语句的左侧的值)。因此,使用decltype理应得到一个该类型的左值引用。

    但是decltype单独作用于对象,没有使用对象的表达式的属性,而是直接获得了变量的类型。

    要想获得变量作为表达式的类型,可以加一个括号:

    int i = 42;

    // 加了括号,变成了表达式
    // 返回的是i的左值形式
    // 因此ri的类型是int &
    decltype((i)) ri = i;
    1
    2
    3
    4
    5
    6
    那么请问,下面的代码,temp是什么类型:

    int i = 42, *p = &i;

    decltype((p)) temp = p;
    1
    2
    3
    解析:decltype作用的是表达式,(p)得到的是p的左值,所以temp一定是一个引用;p是指向int类型的指针,因此decltype得到的是指向int类型的指针的引用。

    4. decltype + 函数
    C++中通过函数的返回值和形参列表,定义了一种名为函数类型的东西。它的作用主要是为了定义函数指针。

    例如:

    // 声明了一个函数类型
    using FuncType = int(int &, int);

    // 下面的函数就是上面的类型
    int add_to(int &des, int ori);

    // 声明了一个FuncType类型的指针
    // 并使用函数add_to初始化
    FuncType *pf = add_to;

    int a = 4;

    // 通过函数指针调用add_to
    pf(a, 2);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    我们可以使用decltype获得函数add_to的类型:

    decltype(add_to) *pf = add_to;
    1
    这样的声明就简单多了。

    ③当使用decltype(func_name)的形式时,decltype会返回对应的函数类型,不会自动转换成相应的函数指针。

    5. 总结
    decltype是为了解决复杂的类型声明而使用的关键字,称作decltype类型说明符。

    decltype可以作用于变量、表达式及函数名。①作用于变量直接得到变量的类型;②作用于表达式,结果是左值的表达式得到类型的引用,结果是右值的表达式得到类型;③作用于函数名会得到函数类型,不会自动转换成指针。

    decltype不会去真的求解表达式的值,可以放心使用。
    ————————————————
    版权声明:本文为CSDN博主「Jinxk8」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/u014609638/article/details/106987131

  • 相关阅读:
    第一次笔记:计算机硬件的工作原理 主存储器 运算器 控制器 计算机的工作过程 计算机系统的层次结构 三种级别的语言
    内质网应激+预后模型新方向,干湿结合搞定5+sci
    MongoDB集群之分片集群 Shard Cluster
    七、定时器类的编写与解析 —— TinyWebServer
    微服务架构中各个组件都需要使用哪些技术?
    软件设计师-UML基础教程
    《LeetCode力扣练习》代码随想录——二叉树(平衡二叉树---Java)
    Spring核心——SPEL概述
    mysql—表单二
    基于SSH的房屋租赁系统的设计与实现
  • 原文地址:https://blog.csdn.net/u012294613/article/details/128032390