转载请注明来源:http://blog.csdn.net/thesys/archive/2010/06/02/5641447.aspx
简介
C++0x为了增加自动类型推断的特性,修改了auto这个关键字的含义,这个关键字在现行C++标准中表示生存期为自动,写不写它效果是一样的,几乎就是一废物。因此这次C++0x废物利用,扩展了它的含义,用来表示从初始化表达式自动类型推断了(下面简称自动类型推断)。
最典型的用法如下:
auto x = expression;
x的类型将由等号后面表达式的类型来确定,最明显的好处是,对于某些复杂类型,我们不用再明确写出其类型,例如我们经常遇到的对STL容器遍历时,写的那个迭代器类型。
除了直接声明auto类型的变量外,还可以组合成较复杂的形式,例如:
auto& x = expression;
auto const& x = expression;
auto* x = expression;
auto const* x= expression;
auto x[100] = expression;
说明
auto关键字是一个占位符(placeholder),表示待推断的类型,主要用于变量的初始化表达式,它可以其它的类型修饰符联合使用,包括const, volatile等,例如:
auto score = 100; // score的类型是int
auto volatile pi = 3.14; // pi的类型是double volatile
auto const* msg = "hello, world"; // msg的类型是char const*
自动类型推断,可以应用在全局变量,局部变量,静态局部变量,静态全局变量,类的静态常量成员变量这几个地方。但不能用于函数的参数,模板参数,类的非静态成员变量,类的静态非常量成员变量。(不过GCC4.5的实现有个bug, 可以用于类的静态非常量成员变量,但定义完了却无法访问,报告说找不到这个变量,但又可以对这个变量取typeid,总之是个bug)
使用auto关键字进行自动类型推断,其推断规则完全沿用模板参数类型推断规则,可以简单地认为auto关键字的类型就是函数模板中参数T的类型。例如:
auto x1 = expression1;
template<typename T1>
void func1(T1 t1);
func1(expression1);
auto* x2 = expression2;
template<typename T2>
void func2(T2* t2);
func2(expression2);
1: template <typename T>
2: struct X{};
3:
4: template <typename T>
5: X makeX(T);
6:
7: template <typename T>
8: void f(X t);
9:
10: void test()
11: {
12: f(makeX(100)); // 正确,对于f函数模板来说,T被推导为int类型
13: X<auto> x = makeX(100); // 错误,auto不能用于模板参数。挺遗憾的,因为支持这个并不难。
14: }
自动类型推断通常只能用于变量的初始化语句,变量的定义后面必须跟有非空非void表达式,而该表达式有两种可选形式:=expression;和(expression),例如下面两行代码是等价的:
auto x = 100;
auto x(100);
对于一个初始化语句中定义多个变量的情况,对于所有变量的定义,所推导出来的auto,必须代表同一个类型,否则就为错。例如:
int a = 1;
auto i = 100, *p = &a; // 正确,auto被推导为int
auto c = 'A', d = 3.14; //错误,无法将auto推导为一致的类型
auto不可用于推导数组类型,如果auto出现在数组变量定义的方括号前面,则编译出错。而且对于等号右边的表达式是数组的情况,等号左边的类型会被推断为指针,例如:
1: int t1[5];
2: int t2[5][3];
3:
4: auto x1 = t1; // x1的类型是int*
5: auto x2 = t2; // x2的类型是int(*)[3]
6: auto* x3 = t2; // x3的类型是int(*)[3]
7: auto x4 = {1, 2}; // 对于GCC4.5,x4是std::initializer_list类型,
8: // 对于VC10,报错C2078,还不支持initializer_list
9:
10: auto y1[] = t1; // 错误,auto不能出现在数组定义的[]前
11: auto y2[3] = {1,2,3}; // 错误,auto不能出现在数组定义的[]前
12: auto y3 = {}; // 错误,无法推断出std::initializer_list的类型参数
auto关键字在用于创建对象有点特别,它可以和new一起调用拷贝构造函数来创建一个对象,例如:
1: auto x1 = new auto(1); // 正确,x1为int*
2: int* x2 = new auto(2); // 正确,x2为int*
3: auto y1 = auto(1); // 错误
4: int y2 = auto(1); // 错误
auto用于推断有继承关系的类的时候,可能有些令人混淆,例如:
1: struct Base
2: {
3: virtual void func()
4: {
5: cout << __LINE__ << endl;
6: }
7: };
8:
9: struct Derived : public Base
10: {
11: virtual void func()
12: {
13: cout << __LINE__ << endl;
14: }
15: };
16:
17: Derived* dptr = new Derived();
18: Base* bptr = dptr;
19: auto x1 = *bptr; // x1的类型是Base
20: auto& x2 = *bptr; // x2的类型是Base&
21: x1.func(); // 调用Base::func
22: x2.func(); // 调用Derived::func