类型别名(type alias)一个名字,是某种类型的同义词。使用类型名有很多好处,能让复杂的类型名字变得简单明了,易于理解和使用。

有两种方法可用于定义类型别名。传统的方法是使用关键字typedef :

typedef double wages; //wages是double的同义词
typedef wages base, *p;  //base是double的同义词, p是double*的同义词

含有typedef的声明语句定义的不再是变量而是类型别名。

新标准规定了一种新方法,使用别名声明(alias declaration)来定义类型的别名:

using SI = Sales_item; //SI是Sales_item的同义词

用关键字using作为别名声明的开始,其后紧跟别名和等号,是作用是吧等号左侧的名字规定成等号右侧类型的别名。

类型别名和类型的名字等价,只要是类型的名字能出现的地方,就能使用类型别名:

wages hourly, weekly;  //等价于double hourly、weekly;
SI item;  //等价于Sales_item item

指针、常量和类型别名

如果摸个类型别名指代的是复合类型或常量,那么把它用到声明语句里就会产生意想不到的后果。

例如类型pstring,它实际上是类型char*的别名:

typedef char *pstring;
const pstring cstr = 0;  // cstr是指向char的常量指针
const pstring *ps; //ps是一个指针,它的对象时指向char的常量指针

当遇到一条使用了类型别名的声明语句时,人们往往会错误的尝试把类型别名替换成它本来的样子,以理解该语句含义:

const char *cstr = 0; //是对const pstring cstr的错误理解

再次强调这种理解是错误的。声明语句中用到pstring时,其基本数据类型是指针。可是用char*重写了声明语句后,数据类型就变成了char,*成为了声明符的一部分。这样改写的结果是,const char成了基本数据类型。前后两种声明含义截然不同,前者声明了一个指向char的常量指针,改写后的形式则声明了一个指向const char的指针。

auto 类型说明符

auto让编译器通过初始值来推算变量的类型。显然,auto定义的变量必须有初始值:

//由val1和val2相加的结果可以推断出item的类型
auto item = val1+val2; //item初始化为val1和val2相加的结果

使用auto也能在一条语句中声明多个变量:

auto i = 0, *p = &i;  //正确: i是整数、p是整型指针
auto sz = 0, pi = 3.14;  //错误:sz和pi的类型不一致

复合类型、常量和auto

编译器一引用对象的类型作为auto的类型:

int i = 0, &r = i;
auto a = r;  //a是一个整数(r是i的别名,而i是一个整数)

其次,autu一般会忽略掉顶层const,同时底层const则会保留下来,比如当初始值是一个指向常量的指针时:

const int ci = i,&cr = ci;
auto b = ci; //b是一个整数(ci的顶层const特性被忽略掉了)
auto c = cr; //c是一个整数(cr是ci的别名,ci本身是一个顶层const)
auto d = &i; //d是一个整型指(整数的地址就是指向整数的指针)
auto e = &ci; //e是一个指向整数常量的指针(对常量对象取地址是一种底层const) ci是整数常量

如果希望推断出的auto类型是一个顶层const,需要明确指出:

const auto f = ci; //ci的推演类型是int,f是const int

还可以将引用的类型设为auto,此时原来的初始化规则仍然适用:

auto &g = ci; //g是一个整型常量引用,绑定到ci
auto &h = 42; //错误:不能为非常量引用绑定字面值
const auto &j = 42; //正确:可以为常量引用绑定字面值

要在一条语句中定义多个变量,切记,符号&和*指从属于某个声明符,而非基本数据类型的一部分,因此初始值必须是同一类型:

auto k = ci, &l = i;  //k是整数,l是整型引用
auto &m = ci,  *p = &ci;  //m是对整型常量的引用,p是指向整型常量的指针//错误: i的类型是int而&ci的类型是const int
auto &n = i, *p2 = &ci;  //如上所说的类型不符 错误

decltype类型指示符

Decltype它的作用是选择并返回操作数的数据类型。再次过程中,编译器分析表达式并得到它的类型,却不实际计算表达式的值:

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

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

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

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是一个引用,必须初始化

需要指出的的是,引用从来都是作为其所指对象的同义词出现,只有用在decltype处是一个例外。

decltype和引用

如果decltype使用的表达式不是一个变量,则decltype返回表达式结果对应的类型。

有些表达式将向decltype返回一个引用类型。一般来说这一维和表达式的结果对象能作为一个赋值语句的左值:

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

因为r是一个引用,因此decltype(r)的结果是引用类型。而r+0显然结果将是一个具体值而非一个引用。

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

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

明显调用的表达式前的括号必须具有指针函数类型_每天三分钟带你搞懂C++基础Day5 处理类型 typedef、auto、decltype...相关推荐

  1. VS报错 明显调用的表达式前的括号必须具有(指针)函数类型的一种 超简单改正方法

    背景:用VS编写代码时报了没见过的bug----明显调用的表达式前的括号必须具有(指针)函数类型 解决办法:检查括号内内容是否正确,不是函数的成员,不要加() 例我的错为:message->se ...

  2. 明显调用的表达式前的括号必须具有指针函数类型_基于指针对象的方法

    " 本文来源于<The Go Programming Language>" 6.2. 基于指针对象的方法 当调用一个函数时,会对其每一个参数值进行拷贝,如果一个函数需要 ...

  3. 明显调用的表达式前的括号必须具有函数类型_Chisel(二) Scala语法 变量与函数...

    变量: Scala在定义一个变量时,必须在其变量名前添加关键字"var"或"val"这两者的区别是"var"修饰的变量可以新赋值,并把原值抛 ...

  4. 一文搞懂python3基础大全(变量,标准数据类型,标识符,行与缩进,运算符和表达式,条件语句if,循环语句,函数,文件,面向对象,错误和异常,模块)

    2.Python3基础 2.1.变量 Python 中的变量不需要声明.每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建.变量没有类型,"类型"是变量所指的内存中对象的类型 ...

  5. python 自动补全函数括号_三分钟,让你弄清楚Python中函数的括号使用

    喜欢编程,热爱分享,希望能结交更多志同道合的朋友,一起在学习Python的道路上走得更远! 一直以来对python中函数括号的使用,有点分不清楚,到底什么时候用括号,什么时候不用括号,造成了很大困惑. ...

  6. python怎么快速打括号_三分钟,让你弄清楚Python中函数的括号使用

    一直以来对python中函数括号的使用,有点分不清楚,到底什么时候用括号,什么时候不用括号,造成了很大困惑. 执行结果: 根据结果来分析: 1. x = aaa aaa是一个类名,后面没加括号,打印结 ...

  7. Go 学习笔记(34)— Go 方法声明、方法调用、方法值、方法表达式、切片对象方法、指针对象方法

    1. 方法声明 Go 语言的方法非常纯粹, 可以看作特殊类型的函数, 其显式地将对象实例或指针作为函数的第一个参数, 并且参数名可以自己指定, 而不强制要求一定是 this 或 self .这个对象实 ...

  8. 数据结构算法——判断表达式中的括号是否匹配

    元旦三天假,闲着没事干,就想着复习一下学数据结构时的那些算法吧.本来是想用C语言来写的,无奈啊,三四年没用C了,基本上忘光光,还是用C#来写吧,而且.Net基类库中已经有了栈.队列等的实现,直接拿来用 ...

  9. Stack应用 - 数学表达式(Balanced parentheses)括号完全匹配

    概念 数学表达式常常包含括号,如何确保正确的括号嵌套,有很多算法可以实现.今天介绍一种较为简单的算法,主要用到Python中Stack(堆栈)的概念. 实用list基础数据类型实现栈.众所周知,栈的主 ...

最新文章

  1. Android Popwindow 使用
  2. 解决mysql的乱码问题_完美解决mysql中文乱码的问题
  3. easyui 布局之window和panel一起使用时,拉动window宽高时panel不跟随一起变化
  4. python中如何编写代码输入多个数据并把它们放在一个列表中去_10分钟学习函数式Python...
  5. Android数据结构与算法(一):基础简介
  6. 小米无线网卡linux,NanoPi NEO安装小米随身WiFi
  7. 单片机轻松入门之三:蜂鸣器,单片机驱动蜂鸣器电路
  8. XJTU 算法设计与问题求解作业题 第一周
  9. ios VM snapshot invalid and could not be inferred from settings
  10. Android安装包APK如何解压
  11. 学PS平面设计前,你需要先了解这些
  12. 在没有源码的情况下修改.class文件
  13. Java处理富文本编辑器的图片转为base64编码
  14. 静态网页如何上传附件
  15. 【Mybatis】分页
  16. php mysql自动定时备份_php中实现mysql数据库备份与linux自动定时备份代码
  17. 一个SRM系统应该包含哪些模块?
  18. 数论基础:模奇素数的二次剩余 (1)
  19. TagSupport
  20. react 关于iconfont图标应用和动态图标

热门文章

  1. TCP的三次握手和四次挥手详解
  2. Apache Kylin从入门到精通
  3. 一文看懂边缘云在广电行业的应用
  4. 庚顿数据:实时数据库赋能工业互联网
  5. 使用Git后10件你可能需要“反悔”的事
  6. 日站会——你的站会姿势正确吗?
  7. 高密自智,体小量大,希捷Exos Corvault存储系统为数据洞察赋能
  8. 专访百度集团副总裁袁佛玉:科技创新对普惠金融正在充分发挥“乘数效应”
  9. 华为云战略投入政企市场,发布华为云Stack
  10. 5亿整数的大文件,怎么排序 ?面试被问傻!