C++ Primer:2.5 处理类型

程序复杂,用的的类型也复杂:

  • 类型名复杂,无法明确体现真实目的和含义;
  • 搞不清需要的类型,不得不回头从程序上下文寻求帮助。

类型别名

两种方法定义类型别名:

关键字typedef

含有typedef的声明语句,声明符可以包含类型修饰,也能由基本数据类型构造出复合类型来。

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

别名声明

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

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

指针、常量和类型别名

某个类型别名指代的是复合类型或常量,用到声明语句会有意想不到的结果。

typedef char *pstring;  // pstring是char*的别名,const pstring就是指向char的常量指针,而非指向常量字符的指针
const pstring cstr = 0; // cstr是指向char的常量指针(顶层)
const pstring *ps; // ps是一个指针,它的对象是指向char的常量指针

使用类型别名的声明语句,不能简单的替换进行理解。

auto类型说明符

auto类型说明符,让编译器分析表达式所属的类型,通过初始值来推算变量的类型,auto类型必须有初始值。
使用auto语句也能在一条语句中声明多个变量,一条声明语句只能有一个数据类型,该语句中所有变量的初始基本数据类型必须一样。

复合类型、常量和auto

编译器推断出来的auto类型有时和初始值的类型不完全一样,会适当的改变结果类型使其更符合初始化规则。

  • 使用引用使用的是引用的对象,引用作为初始化其实是引用对象的值,以引用对象的类型作为auto的类型。
  • auto忽略顶层const,底层const保留下来。
int i = 0; 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)
  • 如果推断出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是整数,1是整型引用
auto &m = ci,*p = &ci; // m是对整型常量的引用,p是指向整型常量的指针
auto &n = i,*p2 = &ci; // 错误:i的类型是int而&ci的类型是const int

const int i = 42; // const int
auto j = i; // int 
const auto &k = i; // const int&
auto *p = &i; // const int*
const auto j2 = i, &k2 = i; // const int / const int&

decltype类型指示符

decltype:选择并返回操作数的数据类型,过程中编译器分析表达式并得到他的类型,但不计算表达式的值。

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

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

decltype和引用

  • decltype使用的表达式,则返回表达式结果对应的类型。有些表达式将向decltype返回一个引用类型,该表达式的对象可以中作为一条赋值语句的左值。
//decltype的结果可以是引用类型
int i = 42*p = &i, &r = i;
decltype(r+0) b; // 正确:加法的结果是int,因此b是一个(未初始化的)int
decltype(*p) c;  // 错误:c是int&,必须初始化
  • r是引用,decltype(r)结果是引用类型,decltype(r+0)结果是r所指的类型,具体值而非引用。
  • p是指针,decltype(*p)结果是引用类型,得到指针所指的对象,还能给这个对象赋值。
  • decltype的结果类型与表达式形式密切相关。
    • 如果decltype使用的是一个不加括号的变量,得到的结果是该变量的类型。
    • 如果给加上一层或多层括号,则得到一个表达式,这样的decltype得到引用类型。
// decltype的表达式如果是加上了括号的变量,结果将是引用
decltype((i)) d;   // 错误:d是int&,必须初始化
decltype(i) e;     // 正确:e是一个(未初始化的)int

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

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值