随着程序越来越复杂,程序中用到的类型也越来越复杂,这种复杂性体现在两个方面。一是一些类型难于“拼写”,它们的名字既难记又容易写错,还无法明确体现其真实目的和含义。二是有时候根本搞不清到底需要的类型是什么,程序员不得不回过头去从程序的上下文中寻求帮助。
typedef
typedef来源于 C,可以给类型使用别名:
typedef int size; // size 就代表int typedef double wage, *p; // wage代表double,而p代表double* typedef double adouble[10]; //adouble代表double[10]
第一个很简单,后面的么看?把typedef
去掉看后面的声明,后面的标识符类型是什么,那么代表什么,声明可以千奇百怪,typedef
自然也千奇百怪。在新标准中,可以用using
来替代它:
using p = double*;
有一点要注意:用了这个东西,标识符就是一个整体了,不能像define一样做字符串替换然后又拆开。比如:
typedef char * charp; const charp cp = 0;
charp是一个整体,被const修饰。所以它实际是“常量指针”。要是拆开变成const char *
的话,就成为了“指向常量的指针”,这显然不对。
auto
编程时常常需要把表达式的值赋给变量,这就要求在声明变量的时候清楚地知道表达式的类型。然而要做到这一点并非那么容易,有时甚至根本做不到。为了解决这个问题,C++11新标准引入了auto
类型说明符,用它就能让编译器替我们去分析表达式所属的类型。和原来那些只对应一种特定类型的说明符(比如 double
)不同,auto 让编译器通过初始值来推算变量的类型。显然,auto定义的变量必须有初始值:
auto i = 3 + 2; //从右推左, auto填充为int auto m = 9。0, *p = &m; // auto填充为double auto a = 3, b = 2.0; // 不可以,只能填充一个值 vector<int> v{1, 2, 3, 4}; auto it = v.begin(); // 类型为vector<int>::iterator,避免冗长的声明。
auto
是从右边类型推左边类型,并不是变量声明时的类型。
int i = 0, &r = i; auto a = r; //a是int,不是int& auto &b = r; //引用需显式指定 const int c = 0; auto x = c; // 填充为int,右const被忽略 const auto y = c; // 右const要手动指定 auto p = &c; // 填充为const int *,左const会被保留 int ir[10]; auto x = ir; // 数组名被转化为指针,值int* auto &x = ir; // 数组名还是数组,值为int[10]
auto也有助于提升程序的可拓展性,每个变量的类型都依赖其他变量,只需第一个声明的变量,后面所有变量的类型同时也就更改了,很方便。
auto a = 3; for (auto i(a); i < 12; i++) ...
将a = 3
改为a = 3ll
,则所有变量都被扩展为64位类型。
auto将数组转为指针大不相同
受谭浩强影响,很多人觉得“数组就是指针”。这种说法是错误的。数组就是数组啦,只是某些场合可以转化成元素头指针。C++ Primer里提出一个有趣的例子:
int a[3][3] = {}; for (auto &row: a) //for (auto row: a) for (auto &col: row) cout << col << endl;
上面的代码可以正常运行,但是换成注释语句后就不行了,原因在前面的示例代码里已经提过了。auto &row: a
里,row的类型是int[3]
,是可迭代的。但auto row: a
里,它的类型成为了int*
,不可迭代,自然第二个for执行不了。数组到指针是一种退化,因为只有头地址而丢失了长度。
auto用于函数声明
在更新的版本中,auto还可以用于形参类型和返回值:
auto triple_adder(auto &&a, auto &&b, auto &&c) { return a + b + c; } main() { cout << triple_adder(1, 2, 3.2) << endl; //6.2 cout << triple_adder(string("he"), string("ll"), string("oo")) << endl; //helloo }
将参数声明为auto
,作用与模板完全相同(但更简洁),会根据类型生成多个函数。而返回值设为 auto
,就可以根据return语句的类型自动生成返回类型。不过auto只是代表“自动推断一种类型”。C++的函数返回值只能有一种类型。如果多处return类型不一致,推断失败就会报错。
decltype
decltype
是和 auto 一起推出的,不过没那么简洁,用的不多。decltyle是完整严格的类型推断。
decltype(3) i = 12; // 3的类型是int,所以是int decltype(f()) j = 0; // f的返回类型决定j的类型,但是并不会执行f
与auto
不同,decltype
的规则为“括号里面是什么就是什么”:
const int a = 3; decltype(a) ca = a; //ca 是const int int b = 5, &rb = b; decltype(b) rb = a; //rb 是int& decltype(b+0) rrb = 1; //是int int ar[10]; decltype(ar) p; //是int[10]