auto 指定符(C++11 起)

来自cppreference.com
< cpp‎ | language

对于变量,指定其类型将从其初始化器自动推导而出。

对于函数,指定其返回类型是尾随的返回类型或将从其 return 语句推导出 (C++14 起)

对于非类型模板形参,指定其类型将从参数推导出。 (C++17 起)

目录

[编辑] 语法

auto variable initializer (1) (C++11 起)
auto function -> return type (2) (C++11 起)
auto function (3) (C++14 起)
decltype(auto) variable initializer (4) (C++14 起)
decltype(auto) function (5) (C++14 起)
auto :: (6) (概念 TS)
cv(可选) auto ref(可选) parameter (7) (C++14 起)
template < auto Parameter > (8) (C++17 起)
cv(可选) auto ref(可选) [ identifier-list ] initializer ; (9) (C++17 起)

[编辑] 解释

1) 在块作用域、命名空间作用域、循环初始化语句等中声明变量时,关键词 auto 可用作类型指定符。

只要初始化器的类型被确定,则编译器会用来自函数调用的模板实参推导规则所决定的类型替换关键词 auto (细节见模板实参推导)。关键词 auto 可与修饰符组合,如 const& ,它们将参与类型推导。例如,给出 const auto& i = expr;i 的类型恰是虚构模板 template<class U> void f(const U& u) 中参数 u 的类型,倘若函数调用 f(expr) 被编译。从而, auto&& 可根据初始化器被推导成左值或是右值引用,这被用于基于范围的for循环。

auto 被用于声明多个变量,则推导类型必须相符。例如,声明 auto i = 0, d = 0.0; 为病式,而声明 auto i = 0, *p = &i; 为良式,这里 auto 被推导成int
2) 在使用尾随返回类型语法的函数声明中,关键词 auto 不进行自动类型检测。它只作为语法的一部分起作用。
3) 在不使用尾随返回类型语法的函数声明中,关键词 auto 指示返回类型将通过其 return 语句的运算数,用模板实参推导规则推导出。
4) 若变量的声明类型是 decltype(auto) ,则关键词 auto 被替换成其初始化器的表达式(或表达式列表),而实际类型以 decltype 规则推导。
5) 若声明函数返回类型为 decltype(auto) ,则关键词 auto 被替换成其返回语句的运算数,而其实际返回类型以 decltype 规则推导。
6) 拥有形式 auto:: 的嵌套名称指定符是占位符,它会被类或枚举类型遵循制约类型占位符推导规则替换。
7) lambda 表达式中的参数声明。 (C++14 起)函数参数声明。 (概念 TS)
8)模板形参声明为 auto ,则其类型由对应使用参数推导出。

[编辑] 注意

C++11 前, auto 拥有存储期指定符的语义。

不允许在一个声明中混合 auto 变量和函数,如 auto f() -> int, i = 0;

[编辑] 示例

该示例显示用一种 typeinfo::name 打印完整类型名的实现的输出;如使用 gcc 或相似者,可通过 c++filt -t 过滤输出。

#include <iostream>
#include <cmath>
#include <typeinfo>
 
template<class T, class U>
auto add(T t, U u) -> decltype(t + u) // 返回类型是 operator+(T, U) 的类型
{
    return t + u;
}
 
auto get_fun(int arg) -> double (*)(double) // 等同于: double (*get_fun(int))(double)
{
    switch (arg)
    {
        case 1: return std::fabs;
        case 2: return std::sin;
        default: return std::cos;
    }
}
 
int main()
{
    auto a = 1 + 2;
    std::cout << "type of a: " << typeid(a).name() << '\n';
    auto b = add(1, 1.2);
    std::cout << "type of b: " << typeid(b).name() << '\n';
    auto c = {1, 2};
    std::cout << "type of c: " << typeid(c).name() << '\n';
    auto d = new auto{3.f};
    std::cout << "type of d: " << typeid(d).name() << '\n';
    delete d;
 
    auto my_lambda = [](int x) { return x + 3; };
    std::cout << "my_lambda: " << my_lambda(5) << '\n';
 
    auto my_fun = get_fun(2);
    std::cout << "type of my_fun: " << typeid(my_fun).name() << '\n';
    std::cout << "my_fun: " << my_fun(3) << '\n';
 
//  auto int x; // C++11 开始错误:"auto" 不再是存储类指定符
}

可能的输出:

type of a: int
type of b: double
type of c: std::initializer_list<int>
type of d: float*
my_lambda: 8
type of my_fun: double (*)(double)
my_fun: 0.14112