我们经常会将表达式的值赋给变量,这就要求在变量声明时清楚地知道表达式的类型。有时候是很复杂的一件事,在C++11中引入了auto类型说明符,用它就能让编译器替我们去分析表达式所属的类型。当然,auto变量必须有初始值,这样编译器才能推断其类型:
double val1 = 1.1, val2 = 2.2;
auto item = val1 + val2; // item为double类型
使用auto也能在一条语句中声明多个变量。因为一条语句只能有一个基本数据类型,因此该语句中所有变量的初始基本类型必须一致:
auto i0 = 0, *pI = &i0; // ok, i0为int类型, p为int指针
auto sz = 0, pi = 3.14; // fail, sz和pi类型不一致
复合类型、const和auto
编译器推断出来的auto类型有时候和初始值类型不完全一致,编译器会适当的改变结果类型使其更符合初始化规则。
引用:使用引用实际上使用的是引用的对象,当引用被用作初始化时,真正参与初始化的其实是引用对象的值。此时,编译器以引用对象的类型作为auto的类型:
int i = 0, &r = i;
auto a = r; // a是一个int,r是i的别名,而i是一个int
auto一般会忽略掉顶层const,而会保留底层const,比如当初始值是一个指向常量的指针时:
const int ci = i, &cr = ci;
auto b = ci; // b是一个int,ci的顶层const被忽略
auto c = cr; // c是一个int,cr的顶层const被忽略
auto d = &i; // d是一个int型指针
auto e = &ci; // e是一个指向整型常量的指针,对常量对象取地址是一种底层const
若希望推断出的auto类型是一个顶层const,需要明确支出:
const auto f = ci;
还可以将引用类型设置为auto,原来的初始化规则仍然适用,初始值的顶层const属性会被保留:
auto &g = ci; // g是一个整型常量引用,绑定到ci
auto &h = 42; // error, 不能为非常量引用绑定字面值
const auto &j = 42; // ok,可以为常量引用绑定字面值
要在一条语句中定义多个变量,符号&和*只从属于某个声明符,而非基本数据类型的一部分,因此初始值必须是同一类型:
auto k = ci, &l = i; // k是int, l是int&
auto &m = ci, *p = &ci; // m是对整型常量的引用,p是指向整型常量的指针
auto &n = i, *p2 = &ci; // error, n是对整型的引用,p2是指向整型常量的指针
一些额外的例子:
const int i = 42;
auto j = i; // j是int
const auto &k = i; // k是int i的常量引用
auto *p = &i; // p是指向整型常量i的指针
const auto j2 = i, &k2 = i; // j2是整型常量, k2是int i的常量引用