首页 > 编程语言 >C++ decltype 类型知识符

C++ decltype 类型知识符

时间:2024-09-15 21:03:48浏览次数:7  
标签:decltype 变量 int 知识 C++ 引用 类型 表达式

希望从表达式的类型推断出要定义的变量的类型,但是不想用该表达式的值初始化变量。

decltype(f())sum =x;  //sum的类型就是函数f的返回类型

编译器并不实际调用函数f,而是使用当调用发生时f的返回值类型作为sum 的类型。

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

const int ci=0,&cj=ci;
decltype(ci) x=0;       //x的类型是 const int
decltype(cj) y=x;       //y的类型是const int&,y绑定到变量x
decltype(cj) z;         //错误:z是一个引用,必须初始化

因为cj是一个引用,decltype(cj)的结果就是引用类型,因此作为引用的z必须被初始化。需要指出的是,引用从来都作为其所指对象的同义词出现,只有用在decltype处是一个例外

decltype 和引用

如果 decltype 使用的表达式不是一个变量,则 decltype 返回表达式结果对应的类型。如 4.1.1节(第120页)将要介绍的,有些表达式将向 decltype 返回一个引用类型。一般来说当这种情况发生时,意味着该表达式的结果对象能作为一条赋值语句的左值:

// decltype 的结果可以是引用类型
int i=42,*p= &i, &r = i;
decltype(r + 0) b; //正确:加法的结果是int,因此b是一个(未初始化的) int
decltype(*p) c;    //错误:c是int&,必须初始化

因为r是一个引用,因此decltype(r)的结果是引用类型。如果想让结果类型是r所指的类型,可以把r作为表达式的一部分,如r+0,显然这个表达式的结果将是一个具体值一个引用。

另一方面,如果表达式的内容是解引用操作,则 decltype 将得到引用类型。正如我们所熟悉的那样,解引用指针可以得到指针所指的对象,而且还能给这个对象赋值。因此,decltype(*p)的结果类型就是int&,而非int。

decltype 和 auto 的另一处重要区别是,decltype 的结果类型与表达式形式密切相关。有一种情况需要特别注意:对于decltype所用的表达式来说,如果变量名加上了一对括号,则得到的类型与不加括号时会有不同。如果 decltype 使用的是一个不加括号的变量,则得到的结果就是该变量的类型:如果给变量加上了一层或多层括号,编译器就会把它当成是一个表达式。变量是一种可以作为赋值语句左值的特殊表达式,所以这样的 decltype 就会得到引用类型:

//decltype的表达式如果是加上了括号的变量,结果将是引用
decltype((i)) d;//错误:d是int&,必须初始化
decltype(i) e;  //正确:e是一个(未初始化的)int

如何理解:变量是一种可以作为赋值语句左值的特殊表达式?如下:

string s1 = "123";
string s2 = "234";
(s1 + s2) = "567";  // 合法

请参考《C++ Primer》 P483,右值和左值引用成员函数

WARNING

切记:decltype((variable))(注意是双层括号)的结果永远是引用,而decltype(variable)结果只有当variable本身就是一个引用时才是引用




《C++ Primer》 P63

标签:decltype,变量,int,知识,C++,引用,类型,表达式
From: https://www.cnblogs.com/huvjie/p/18415628

相关文章

  • C++ auto 类型推断注意的地方
    inti=0,&r=i;autoa=r;//a是一个整数(r是i的别名,而i是一个整数)intaauto一般会忽略掉顶层const(参见2.4.3节,第57页),同时底层const则会保留下来,比如当初始值是一个指向常量的指针时:constintci=i,&cr=ci;autob=ci;//b......
  • C++的习题
    C++的习题类与对象习题1:(const成员函数)假设AA是一个类,AA*abc()const是该类的一个成员函数的原型。若该函数返回this值,当用x.abc()调用该成员函数后,x的值是()A.可能被改变B.已经被改变C.受到函数调用的影响D.不变A.此成员函数被定义为const常方法,代表在......
  • C++中对象的延迟构造
    本文并不讨论“延迟初始化”或者是“懒加载的单例”那样的东西,本文要讨论的是分配某一类型所需的空间后不对类型进行构造(即对象的lifetime没有开始),更通俗点说,就是跳过对象的构造函数执行。使用场景我们知道,不管是定义某个类型的对象还是用operatornew申请内存,对象的构造函数都......
  • C++ typedef 类型别名注意的地方
    指针、常量和类型别名如果某个类型别名指代的是复合类型或常量,那么把它用到声明语句里就会产生意想不到的后果。例如下面的声明语句用到了类型pstring,它实际上是类型char*的别名typedefchar*pstring;constpstringcstr=0;//cstr是指向char的常量指针constpstring*ps;......
  • 矩阵连乘(动态规划)(C/C++)最详尽代码注释
    写在所有的前面:本文采用C/C++实现代码目录写在所有的前面:题目说明题目题目出处题目描述Description输入Input输出Output样例Sample限制Hint解答说明方案1:最优分隔点法(动态规划)解题思路代码实现c语言头文件:c++头文件主代码部分:(详尽版本1)主代码部分(题目对应版本)其他解......
  • C++链接的那些事
    接上文OK!Rightnow!  Let's go!今天我们来谈谈链接,什么是链接,C++链接实际上做什么的?链接是一个过程,当我们从源C++文件转到实际的可执行文件(二进制文件)。第一阶段是编译源文件,一旦我们把文件编译好,就需要通过一个叫做链接的过程,现在链接的主要工作是找到每个符号和......
  • C++编译 链接 执行那些事
    OK!Rightnow!  Let's go!如何从源文件开始,实际的文本文档到可执行的二进制代码,写C++程序的基本流程。实际是你有一些C++的源文件,然后将这些源文件给到编译器,编译器将其转成二进制的东西,二进制的东西可能是某种库,或者是可执行的程序。在#符号之后的都是预处理语句......
  • 「数组」堆排序 / 大根堆优化(C++)
    目录概述核心概念:堆堆结构数组存堆思路算法过程up()down()Code优化方案大根堆优化Code(pro)复杂度总结概述在「数组」快速排序/随机值优化|小区间插入优化(C++)中,我们介绍了三种基本排序中的冒泡排序与分治思想结合的算法:快速排序。本文我们来讲第二种基本排......
  • 详解c++多态---上
    virtual关键字1.可以修饰原函数,为了完成虚函数的重写,满足多态的条件之一。classPerson{public:virtualvoidBuyTicket(){cout<<"买票-全价"<<endl;}};classStudent:publicPerson{public:virtualvoidBuyTicket(){cout<<"买票-半价"<<......
  • 中间件知识点-消息中间件(Kafka)二
    Kafka一、Kafka介绍及基本原理kafka是一个分布式的、支持分区的、多副本、基于zookeeper的分布式消息系统/中间件。kafka一般不会删除消息,不管这些消息有没有被消费。只会根据配置的日志保留时间(log.retention.hours)确认消息多久被删除,默认保留最近一周的日志消息(日志......