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 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>
my_lambda: 8
type of my_fun: double (*)(double)
my_fun: 0.14112