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类型变量 7 存储在栈区,static类型变量存储在静态 8 区,二者不能同时使用,但在新语法中, 9 auto已经不再作为存储类型指示符, 10 和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类 14 型,但是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不能用于函数的参数
void foo (auto a ) //error
{
cout << typeid (a).name () << endl;
}
使用函数模板代替auto,如下:
template<typename T>
void foo (T a = T ())
{
cout << typeid (a).name () << endl;
}
(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不能用于数组元素
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("张飞"); 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 }