C++auto关键字

auto关键字:

1.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 }    

2.C++11标准中auto关键字不再表示变量的存储类型,而是用于类型推导

(2.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 }                

(2.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 }

(2.3)auto使用的限制

(2.3.1)auto不能用于函数的参数

 1 void foo (auto a )    //error
 2 {
 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.3.2)类的非静态数据成员不能包含auto类型

class A
{
public:
    int m_x = 0;
    //类的非静态数据成员不能包含auto类型
    auto m_y = 1;//error
    static auto const m_z = 2;
};

(2.3.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 }

(2.3.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]
}

(2.4)何时使用auto

(2.4.1)通过auto减少模板的类型参数

 1 class A
 2 {
 3 public:
 4   A(int arg = 0) :m_var(arg){}
 5   int get(void)const
 6   {
 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.4.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 }