auto关键字:
一、C++98标准auto关键字的作用和C语言的相同,表示自动变量,是关于变量存储位置的类型饰词,通常不写,因为局部变量的默认存储就是auto
1 void foo(void)
2 {
3 int a; //变量存储在栈区
4 auto int b; //自动变量,存储在栈区
5 static int c; //静态变量,存储在数据区
6 register int d; //寄存器变量,存储在寄存器中
7 }
参考:C语言中的4中存储类型
二、C++11标准中auto关键字不再表示变量的存储类型,而是用于自动推导表达式或变量的实际类型的
1、auto的基本用法
1 void foo(void)2 {3 auto a = 1; //a是int类型4 auto b = new auto(2); //b是int *类型5 auto const *c = &a; //c是const int *类型6 static auto d = 4.0; //d是double类型,在旧语法中,auto类型变量存储在栈区,static类型变量存储在静态区,二者不能同时使用,但在新语法中,auto已经不再作为存储类型指示符,和 static关键字没有冲突,可以合用
11 auto e; //error,C++11标准中auto变量必须被初始化
12 auto const *f = &a,g = 4.0; //error,类型推导不能带有二义性
13 auto const *h = &a,i; //error,虽然可以根据&a得出auto表示int类型,但是i依然需要显示初始化
15 auto int j = 3; //error,auto不能与其他任何类型说明符组合使用
16
17 auto d=4.38; //double
18 auto s("hello"); //const char*
19 auto z = new auto(10); // int*
20 auto x1 = 5, x2 = 5.0, x3='c';//错误,必须是初始化为同一类型
}
使用C++11的auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。因此auto并非是一种"类型"的声明,而是一个类型声明时的"占位符”,编译器在编译期会将auto替换为变量实际的类型。
2、auto和指针或者引用结合使用
1 void foo(void)2 {3 int a = 0;4 auto *b = &a; //b是int *类型5 auto c = &a; //c是int *类型6 auto &d = a; //d是int&类型7 cout << &d << ' ' << &a << endl; //地址相同8 auto e = d; //e是int类型,当表达式带有引用属性时,auto会抛弃其引用属性,直接推导为原始类型9 cout << &e << ' ' << &a << endl; //地址不同
10 auto const f = a; //f是int const 类型
11 cout<<++f<<endl; //error,f带有常属性
12 auto g = f;
13 cout<<++g<<endl; //g的值为1,当表达式带有CV限定时,auto会抛弃其CV限定
14 auto const &h = a;
15 auto &i = h; //i是int const &类型
16 cout<<++i<<endl; //error,如果auto和引用或者指针结合使用,表达式的CV限定会被保留下来
17 auto *j = &h; //j是int const *类型
18 cout<<++*j<<endl; //error,如果auto和引用或者指针结合使用,表达式的CV限定会被保留下来
19 }
3、auto使用的限制
(1)auto不能用于函数的参数
1 void foo (auto a ) //error2 {3 cout << typeid (a).name () << endl;4 } 5 //使用函数模板代替auto,如下:6 template<typename T>7 void foo (T a = T ())8 {9 cout << typeid (a).name () << endl;
10 }
(2)类的非静态数据成员不能包含auto类型
class A
{
public:int m_x = 0;//类的非静态数据成员不能包含auto类型auto m_y = 1;//errorstatic auto const m_z = 2;
};
(3)auto不能用于模板的类型实参
1 template<typename T>2 class B 3 {4 public:5 B (T const& arg) : m_var (arg) {}6 T m_var;7 }; 8 void main()9 {
10 B<int> b1(0); //true
11 B<auto> b2 = b1; //error,auto不能用于模板的类型实参
12 }
(4)auto不能用于数组元素
void func()
{int arr1[10];auto arr2[10] = arr1; //error,auto不能用于数组元素auto arr3 = arr1; //true,arr3是int *类型,arr1代表数组首地址auto &arr4 = arr1; //true,arr4是int(&)[10]类型,arr1代表数组整体cout << typeid (arr4).name () << endl;//int[10]
}
4、何时使用auto
(1)通过auto减少模板的类型参数
1 class A2 {3 public:4 A(int arg = 0) :m_var(arg){}5 int get(void)const6 {7 return m_var;8 }9 void set(int arg)
10 {
11 m_var = arg;
12 }
13 private:
14 int m_var;
15 };
16
17 class B
18 {
19 public:
20 B(const char *arg):m_var(arg){}
21 const char *get(void)const
22 {
23 return m_var;
24 }
25 void set(const char *arg)
26 {
27 m_var = arg;
28 }
29 private:
30 const char *m_var;
31 };
32
33 //template <typename V,typename X>
34 template <typename X>
35 void foo(X const &x)
36 {
37 //V var = x.get();
38 auto var = x.get();
39 cout << typeid(var).name() << endl;
40 }
41
42 void main(void)
43 {
44 A a(1234);
45 //foo<int> (a);
46 foo(a);// 通过auto减少模板的类型参数
47
48 B b("abcd");
49 foo(b);
50 }
(2)通过auto简化复杂类型的书写
1 void foo(void)2 {3 multimap<string, int> msi;4 msi.insert(make_pair("张飞", 100));5 msi.insert(make_pair("赵云", 90));6 msi.insert(make_pair("关羽", 80));7 msi.insert(make_pair("张飞", 95));8 msi.insert(make_pair("赵云", 85));9 msi.insert(make_pair("关羽", 75));
10 pair<multimap<string, int>::iterator, multimap<string, int>::iterator> range1 = msi.equal_range("张飞");//equal_range()函数查找multimap中键值等于key的所有元素,返回指示范围的两个迭代器。
11 int sum1 = 0;
12 for (multimap<string, int>::iterator it = range1.first; it != range1.second;++it)
13 {
14 sum1 += it->second;
15 }
16 cout << sum1 << endl;
17
18 auto range2 = msi.equal_range("张飞");
19 int sum2 = 0;
20 for (auto it = range2.first; it != range2.second; ++it)
21 {
22 sum2 += it->second;
23 }
24 cout << sum2 << endl;
25 }