C++ 新特性 | C++ 11 | auto 关键字

文章介绍了C++11引入的auto关键字,用于自动类型推导,简化代码编写。内容包括auto的静态类型和动态类型概念,如何使用auto进行类型推导,以及auto的限制和规则,如必须有初始值,处理引用和const/volatile的情况。此外,还讨论了auto在定义冗长类型、泛型编程和配合lambda表达式时的应用。
摘要由CSDN通过智能技术生成


前言:

在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、如果表达式是constvolatile(或两者都有),则去除const/volatile语义

const int NUM = 30;
auto value1 = NUM;           // value1的类型是 int
const auto value2 = NUM;     // value2的类型是 const int

3.4、函数或模板参数不能被声明为auto

在C++中,函数或模板的参数不能直接声明为autoauto关键字主要用于自动类型推导,但它主要用于局部变量和模板中的自动类型推导(在模板参数中,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++编程中发挥重要作用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值