[C++]现代C++语言核心特性解析 Chapter 3

auto占位符(C++11~C++17)

1 重新定义的auto关键字

C++11标准赋予了auto新的含义:声明变量时根据初始化表达式自动推断该变量的类型、声明函数时函数返回值的占位符。

1
2
3
4
5
6
auto i = 5;                      // 推断为int
auto str = "hello auto"; // 推断为const char*
auto sum(int a1, int a2)->int // 返回类型后置,auto为返回值占位符
{
return a1+a2;
}

使用auto的时候有4点需要注意:

  1. 当用一个auto关键字声明多个变量的时候,编译器遵从由左往右的推导规则,以最左边的表达式推断auto的具体类型

  2. 当使用条件表达式初始化auto声明的变量时,编译器总是使用表达能力更强的类型

    1
    auto i = true ? 5 : 8.0;    // i的数据类型为double
  3. auto无法声明非静态成员变量。

    • 在c++11中静态成员变量可以使用auto声明并初始化,但必须是const的。

    • 在c++17中去掉了必须是const的限定,但仍然只支持静态成员变量。

      1
      2
      3
      struct sometype {
      static inline auto i = 5; // C++17
      };
  4. 按照C++20之前的标准,无法在函数形参列表中使用auto声明形参(注意,在C++14中,auto可以为lambda表达式声明形参

    1
    void echo(auto str) {…} // C++20之前编译失败,C++20编译成功

2 推导规则

  1. 如果auto声明的变量是按值初始化(没有使用引用和指针),则推导出的类型会忽略cv限定符。
  2. 使用auto声明变量初始化时,目标对象如果是引用,则引用属性会被忽略
  3. 使用auto和万能引用声明变量时(见第6章),对于左值会将auto推导为引用类型
  4. 使用auto声明变量,如果目标对象是一个数组或者函数,则auto会被推导为对应的指针类型
  5. 当auto关键字与列表初始化组合时,这里的规则有新老两个版本,这里只介绍新规则(C++17标准)。
    • 直接使用列表初始化,列表中必须为单元素,否则无法编译,auto类型被推导为单元素的类型。
    • 用等号加列表初始化,列表中可以包含单个或者多个元素,auto类型被推导为 std::initializer_list<T> ,其中T是元素类型。请注意,在列表中包含多个元素的时候,元素的类型必须相同,否则编译器会报错。

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
using namespace std;


class Base
{
public:
virtual void f()
{
cout << "Base::f()" << endl;
}
};

class Derived : public Base
{
public:
void f() override
{
cout << "Derived::f()" << endl;
}
};

int main()
{
Base *b = new Derived();
auto b1 = *b;
auto &b2 = *b;
cout << "b "; b->f();
cout << "b1 "; b1.f();
cout << "b2 "; b2.f();
}

结果

3 什么时候使用auto

  1. 当一眼就能看出声明变量的初始化类型的时候可以使用auto。

    比如迭代器等。

  2. 对于复杂的类型,例如lambda表达式、bind等直接使用auto。

4 返回类型推导

C++14标准支持对返回类型声明为auto的推导。

1
auto sum(int a1, int a2) { return a1 + a2; }

需要注意的是,如果函数中有多个返回语句,需要保证每个返回语句返回的类型是一致的。

5 lambda表达式中使用auto类型推导

在C++14标准中我们还可以把auto写到lambda表达式的形参中,这样就得到了一个泛型的lambda表达式。

1
2
auto l = [](auto a1, auto a2) { return a1 + a2; };
auto retval = l(5, 5.0);

ambda表达式返回auto引用的方法

1
2
3
4
auto l = [](int &i)->auto& { return i; };
auto x1 = 5;
auto &x2 = l(x1);
assert(&x1 == &x2); // 有相同的内存地址

6 非类型模板形参占位符

C++17标准对auto关键字又一次进行了扩展,使它可以作为非类型模板形参的占位符。当然,我们必须保证推导出来的类型是可以用作模板形参的,否则无法通过编译.

C++中模板参数不能为double类型。


[C++]现代C++语言核心特性解析 Chapter 3
https://erlsrnby04.github.io/2024/10/09/C-现代C-语言核心特性解析-Chapter-3/
作者
ErlsrnBy04
发布于
2024年10月9日
许可协议