文章目录
前言:
在C++11及以后的版本中,
auto
关键字被引入,用于自动类型推导。它允许编译器根据初始化表达式自动推断变量的类型,从而简化了代码编写,并提高了代码的可读性和可维护性。
一、auto
关键字
1、静态类型,动态类型和类型推导
在编程语言分类中,C/C++C常常被认为是静态类型的语言。而有的编程语言则号称是动态类型的,比如python。通常情况下,“静”和“动”的区别是非常直观的。看看下面这段简单的python代码
name=‘world\n’
print 'hello, ' %name
这段代码中python中输出
hellow,world
的实现。这就是编程语言中的动态类型,在运行时来进行类型检查,而C++中类型检查是在编译阶段。动态类型语言能做到在运行时决定类型,主要归功于一技术,这技术是类型推导。
不同于python等动态类型语言的运行时变量类型推导,隐式类型定义的类型推导是发生在编译期,它的作用是让编译器自动推断出这个变量的类型。
2、使用 auto
进行类型推导
在之前的 C++ 版本中,
auto
关键字用来指明变量的存储类型,它和static
关键字是相对的。auto
表示变量是自动存储的,这也是编译器的默认规则,所以写不写都一样,一般也不写,这使得auto
关键字的存在变得非常鸡肋。
C++11 赋予
auto
关键字新的含义,使用它来做自动类型推导。也就是说,使用了auto
关键字以后,编译器会在编译期间自动推导出变量的类型,这样就不用手动指明变量的数据类型了,如下:
auto n = 2;
auto f = 1.8;
auto p = &n;
auto str = "my test";
注意: auto 仅仅是一个占位符,在编译器期间它会被真正的类型所替代。或者说,C++ 中的变量必须是有明确类型的,只是这个类型是由编译器自己推导出来的。
3、auto
限制和规则
3.1、使用auto
关键字的变量必须有初始值
使用
auto
类型推导的变量必须马上初始化,这个很容易理解,因为auto
在 C++11 中只是占位符,并非如int
一样的真正的类型声明。如果使用auto
关键字的变量没有进行初始化编译时会报错,如下:
int main()
{
auto a;
return 0;
}
编译报错:
error: declaration of 'auto a' has no initializer
3.2、如果表达式是引用,则去除引用语义
int a = 20;
int &b = a;
auto c = b; // 此时c的类型被推导为int,而不是int&
auto& c = b; // 此时c的类型才是int&
3.3、如果表达式是const
或volatile
(或两者都有),则去除const/volatile
语义
const int NUM = 30;
auto value1 = NUM; // value1的类型是 int
const auto value2 = NUM; // value2的类型是 const int
3.4、函数或模板参数不能被声明为auto
在C++中,函数或模板的参数不能直接声明为
auto
。auto
关键字主要用于自动类型推导,但它主要用于局部变量和模板中的自动类型推导(在模板参数中,auto
作为占位符,但其含义与局部变量中的自动类型推导不同)。
对于函数参数,你不能直接使用
auto
来声明参数类型,因为编译器在编译时需要知道每个参数的确切类型,以便进行类型检查和调用约定。
3.5、auto
不能声明类型别名
auto
本身不能用来声明新的类型别名。如果需要类型别名,应使用typedef
(在C++11之前)或using
(C++11及以后)关键字。
4、auto
使用场景
4.1、使用auto
定义冗长的类型
使用迭代器时,使用
auto
使代码更加简洁,如下:
// 不使用auto的场景
vector<vector<string>> vec;
for(vector<vector<string>>::iterator i = vec.begin();i != vec.end(); i++)
{
/**/
}
// 使用auto使代码更加简洁
vector<vector<string>> vec;
for(auto i = vec.begin();i != vec.end(); i++)
{
/**/
}
4.2、auto
用于泛型编程
在模板编程中,
auto
的作用尤为突出。由于模板参数的类型在编译时才能确定,因此使用auto
可以方便地声明与模板参数类型相同的变量,而无需显式指定类型。 在定义模板函数时,用于声明依赖模板参数的变量类型。如果不使用auto
就要增加一个模板参数指定变量类型,如下:
template <typename _Tx,typename _Ty>
void add(_Tx x, _Ty y)
{
auto sum = x+y;
cout << "sum:"<<typeid(sum).name() << endl;
std::cout << sum;
}
模板函数返回值依赖模板参数的变量类型,下面是在C++ 14之后可以使用的写法,如下:
template <typename _Tx, typename _Ty>
auto add(_Tx x, _Ty y)->decltype(x+y)
{
return x+y;
}
4.3、auto
配合lambda
使用
auto
推断lambda
类型
auto fun = [](int x, int y){return x + y;};
auto v = fun(1,2);
如果不使用
auto
,则需要使用std::function
来存储
std::function<int(int,int)> fun = [](int x, int y){return x + y;};
auto v = fun(1,2);
4.4、auto
用于返回类型推导
在C++14及以后的版本中,
auto
还可以与返回类型推导(trailing return type)结合使用,以简化模板函数的返回类型声明。
template<typename T, typename U>
auto add(T a, U b) -> decltype(a + b) {
return a + b;
}
// 调用示例
auto result = add(1, 2.5); // 返回类型为double
5、总结
auto
关键字是现代C++编程中一个非常重要的特性,它通过自动类型推导极大地简化了代码的编写过程。然而,在使用auto
时,我们也需要注意其限制和注意事项,以确保代码的正确性、可读性和可维护性。随着C++语言的不断发展,auto
关键字及其相关特性将继续在C++编程中发挥重要作用。