类型处理
(一)类型别名
类型别名是另一个类型名字的同义词。,它能简化复杂的类型的定义,使这些类型使用起来更容易。类型别名也让我们知道了这个类型是干什么的。
定义:(1)使用typedef。
例:typedef double wages; typedef wages base,*p;//base是double类型,pdouble*类型。
typedef是声明中基类型的一部分。包含typedef的声明定义的是别名而不是变量。
像其他声明一样,声明可以包含定义基类型中的复合类型的类型修饰语。
(2)使用using。
例:using SI = Sales_items; SI item;
别名的定义以关键字using开始,后面是”别名“,后面是=,最后是具体的类型。
这种别名定义方式在=左边为等号右边的类型定义了别名。
当使用别名代表复合类型和const类型时能产生令人惊讶的结果。
例:typedef char *pstring; const pstring cstr = 0; const pstring *ps;
在这个声明中的基类型是const pstring。通常来讲,出现在基类型中的const修饰的是给定的类型。所以pstring是指向char的指针(pstring是指针类型),const pstring是一个常数(constant)指针指向char类型,而不是指向const char。(const修饰的是指针类型)
所以上面不等价于const char *cstr = 0;
(二)自动(auto)类型
当不确定一个表达式的值的时候,可以让编译器自己为我们算出具体的类型通过使用类型说明符auto。
auto让编译器通过初始化推断出应有的类型。所以,一个用auto定义其类型的变量必须进行初始化。
可以用auto在一行定义多个变量,只要它们的类型互相都是相同的。
例:auto item = val1+val2;
有时auto判断出来的类型并不是那么准确地和初始化的类型相同,编译器会进行类型调整以使它符合标准的初始化规则。
(1)当我们使用一个引用时,我们真正使用的是引用所引用的那个对象。编译器使用被引用对象的类型进行初始化。
(2)auto通常会忽略顶层const(top-level const)(将const省去)。在初始化时,比如当”初始化值“是指向const的指针的话,底层const(low-level const)是被保留下来的。
如果我们想要得到顶层const,我们要明确地进行说明:在auto前面加上const。
我们也可以指定一个引用类型是auto的,正常的初始化规则仍然适用。
不能将一个const或是非const引用与literal(类似常数)绑定。
当一个引用类型是auto时,顶层const在初始化时不能被忽略。和以前一样,当将引用与初始化进行绑定时,consts就不是顶层的了。
(三)decltype(类型获取)说明符
有时我们想用一个编译器推断出来的表达式的返回类型作为变量的定义类型,但是我们又不希望用这个表达式对该变量进行初始化,在这种情况子下,新标准里面定义了另一个类型说明符——decltype,它能返回它的操作数的类型。
编译器分析表达式的返回类型但是并不计算表达式的值。
例:decltype(f()) sum = x;
decltype处理顶层const和引用的方式与auto不同。
当我们提供给decltype的操作数是变量时,decltype返回这个变量的类型,包括顶层const和引用。
值得注意的是:一个被定义为引用的对象并没有被像这个引用所绑定的对象的同义词那样同等对待。如下ci与cj待遇不一样。
例:const int ci = 0 , &cj = ci;
decltype(ci) x = 0; //x的类型是const int
decltype(cj) y = x; //y的类型是const int&,并且它绑定了x
decltype(cj) z;//出错:z是一个引用,所以并且进行初始化
当我们提供个哦decltype的不是变量而是表达式的时候,我们得到的是表达式返回的类型。
有些表达式会使decltype得到一个引用类型。通俗来讲,decltype为能够产生’在赋值号左边的对象‘的表达式返回一个引用类型。
例:int i = 42, *p = &i, &r = i;
decltype(r+0) b;//可以,b是未被初始化的int类型变量
decltype(*p) c;//出错,c是一个int& 类型,因此必须被初始化
此时r是引用类型,decltype(r)会得到一个引用类型。
如果想得到r所引用的类型,就让r在一个表达式里面,例如r+0,此时就会得到一个非引用的类型。
另一方面,解引用操作符*也可能会返回一个引用类型,当解引用一个指针时,我们得到的是指针所指向的那个对象。
在decltype和auto之间的另一个重要的区别是:decltype判断类型时依赖于给定的表达式的形式。
如果给decltype里面的变量加上括号(),那么对于返回的结果是有影响的。
当decltype里面的变量不加任何括号是,返回的类型是这个变量的类型。
如果加上了括号,编译器会把加上括号的变量当做一个表达式来计算。变量在赋值的左边是,它是一个表达式。
而decltype加上括号的变量通常得到的都是一个引用。
注意:decltype((variable))(双括号)通常返回的是引用类型。但是decltype(variable)只有当变量是引用类型时返回的才是一个引用类型。