持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第25天,点击查看活动详情
auto基本用法
在 C++11 之前的版本(C++98 和 C++ 03)中,定义变量或者声明变量之前都必须指明它的类型,比如 int、char 等;但是在一些比较灵活的语言中,程序员在定义变量时可以不指明具体的类型,而是让编译器(或者解释器)自己去推导,这就让代码的编写更加方便。
C++11 为了顺应这种趋势也开始支持自动类型推导了!C++11 使用 auto 关键字来支持自动类型推导。
auto 关键字基本的使用语法如下:
auto name = value;
name 是变量的名字,value 是变量的初始值。
注意:auto 仅仅是一个占位符,在编译器期间它会被真正的类型所替代。或者说,C++ 中的变量必须是有明确类型的,只是这个类型是由编译器自己推导出来的。
auto 类型推导的简单例子:
auto n = 10; //int
auto f = 12.8; //double
auto p = &n; //int*
auto url = "http://c.biancheng.net/cplus/";//const char*
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 x = 27;
const auto cx = x;
const auto& rx = x;
auto&& uref1 = x;//int&
auto&& uref2 = cx;//const int&
auto&& uref3 = 27;//int&&
std::initializer_list
在C++11中引入了统一初始化列表,相对应的则是std::initializer_list模板类型。
auto x1 = {1,2,3}; //此时x1被推导为std::initializer_list<T>
auto x1 = {1,2,3.0}; //error, 始化列表是模板类型,因此所有的元素必须是同一类型,否则会初始化失败
auto x = {11,23,9}
template<typename T>
void f(T param);
f(x); //编译错误,无法进行推导。
template<typename T>
void f(std::initializer_list<T> param);
f(x); //编译错误,无法进行推导。
auto用于推导函数的返回类型,auto是不能推导初始化列表的。
auto createInitList() { //C++14支持这种写法,C++11中需要结合decltype
return { 1,2 ,3 };
}
不能作为lambda的参数,注意是lambda的参数,普通函数的参数是可以的,C++11中不支持lambda的参数使用auto,C++14开始支持。
auto lda = [](const auto& v) {};
lda({1,2,3}); //编译出错,无法推导初始化列表。
数组
const char name[] = "test";
auto arr1 = name; //arr1的类型是const char*类型
auto& arr2 = name; //arr2的类型是const char(&)[5]
函数
void someFunc(int,doubel);
auto func1 = someFunc; //void(*)(int,double)
auto& func2 = someFunc; //void(&)(int,double)
auto 的应用
使用 auto 定义迭代器
auto 的一个典型应用场景是用来定义 stl 的迭代器。
vector< vector<int> > v;
vector< vector<int> >::iterator i = v.begin();
auto i = v.begin(); //使用 auto 代替具体的类型
auto 用于泛型编程
auto 的另一个应用就是当我们不知道变量是什么类型,或者不希望指明具体类型的时候,比如泛型编程中。
#include <iostream>
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/";
}
};
不用auto
template <typename T1, typename T2> //额外增加一个模板参数 T2
void func(void){
T2 val = T1::get();
cout << val << endl;
}
int main(void){
//调用时也要手动给模板参数赋值
func<A, int>();
func<B, const char*>();
return 0;
}
用auto
template <typename T>
void func(void){
auto val = T::get();
cout << val << endl;
}
int main(void){
func<A>();
func<B>();
return 0;
}
auto的限制
auto 不能在函数的参数中使用
f(auto x); //error
auto 不能作用于类的非静态成员变量(也就是没有 static 关键字修饰的成员变量)中。
auto 关键字不能定义数组,比如下面的例子就是错误的:
auto str[] = url; //arr 为数组,所以不能使用 auto
auto 不能作用于模板参数
template <typename T>
class A{
};
int main(){
A<int> C1;
A<auto> C2 = C1; //错误
return 0;
}