C++ auto关键字
目录
- auto 类型推导的语法和规则
- 历史
- 基本使用
- auto的高级使用
- auto的限制
- auto的应用
- 使用auto定义迭代器
- 使用auto用于泛型编程
C++11 支持使用 auto 关键字来支持自动类型推导。
auto 类型推导的语法和规则
历史
过去:
在之前的 C++ 版本中,auto 关键字用来指明变量的存储类型,它和 static 关键字是相对的。
auto 表示变量是自动存储的,这也是编译器的默认规则。
所以写不写都一样,一般也不写,这使得 auto 关键字的存在变得非常鸡肋。
现在:
C++11 赋予 auto 关键字新的含义,使用它来做自动类型推导。编译器会在编译期间自动推导出变量的类型。
基本使用
auto name = value;
auto 仅仅是一个占位符,在编译器期间它会被真正的类型所替代。
auto的高级使用
auto 除了可以独立使用,还可以和某些具体类型混合使用。占位使得auto表示的为“半个类型”。
int x = 0;
auto *p1 = &x; //p1 为 int *,auto 推导为 int
auto p2 = &x; //p2 为 int*,auto 推导为 int*
auto &r1 = x; //r1 为 int&,auto 推导为 int
auto r2 = r1; //r2 为 int,auto 推导为 int
- 当auto遇到&引用:第 5 行代码是需要重点说明的,r1 本来是 int& 类型,但是 auto 却被推导为 int 类型。这表明当
=
右边的表达式是一个引用类型时,auto 会把引用抛弃,直接推导出它的原始类型。
auto和const结合:
int x = 0;
const auto n = x; //n 为 const int ,auto 被推导为 int
auto f = n; //f 为 const int,auto 被推导为 int(const 属性被抛弃)
const auto &r1 = x; //r1 为 const int& 类型,auto 被推导为 int
auto &r2 = r1; //r1 为 const int& 类型,auto 被推导为 const int 类型
- 第 2 行代码中,n 为 const int,auto 被推导为 int。
- 第 3 行代码中,n 为 const int 类型,但是 auto 却被推导为 int 类型,这说明当
=
右边的表达式带有 const 属性时, auto 不会使用 const 属性,而是直接推导出 non-const 类型。 - 第 4 行代码中,auto 被推导为 int 类型,这个很容易理解,不再赘述。
- 第 5 行代码中,r1 是 const int & 类型,auto 也被推导为 const int 类型,这说明当 const 和引用结合时,auto 的推导将保留表达式的 const 类型。
总结:
- 当类型不为引用时,auto 的推导结果将不保留表达式的 const 属性;
- 当类型为引用时,auto 的推导结果将保留表达式的 const 属性。
auto的限制
- 使用auto时必须对变量初始化,才能推断出对应类型
- auto 类型不能作为传入参数
- auto 不能作用于类的非静态成员变量
- auto 关键字不能定义数组
- auto 不能作用于模板参数
auto的应用
使用auto定义迭代器
使用 stl 容器的时候,需要使用迭代器来遍历容器里面的元素。不同容器的迭代器有不同的类型,在定义迭代器时必须指明。而迭代器的类型有时候比较复杂,书写起来比较麻烦。
#include
using namespace std;
int main(){
vector< vector > v;
auto i = v.begin(); //使用 auto 代替具体的类型
return 0;
}
使用auto用于泛型编程
#include
using namespace std;
class A{
public:
static int get(void){
return 100;
}
};
class B{
public:
static const char* get(void){
return "http://c.biancheng.net/cplus/";
}
};
template
void func(void){
auto val = T::get();
cout << val << endl;
}
int main(void){
func();
func();
return 0;
}
如果不使用auto关键字,需要增加模板参数:
#include
using namespace std;
class A{
public:
static int get(void){
return 100;
}
};
class B{
public:
static const char* get(void){
return "http://c.biancheng.net/cplus/";
}
};
template //额外增加一个模板参数 T2
void func(void){
T2 val = T1::get();
cout << val << endl;
}
int main(void){
//调用时也要手动给模板参数赋值
func();
func();
return 0;
}