考虑以下程序:
int add(int x, int y)
{
    return x + y;
}
编译时,编译器会判断 x + y 的结果为 int,并确保返回值类型与函数声明的返回类型匹配(或可转换)。
返回类型推导:使用 auto
从 C++14 开始,auto 被扩展用于函数返回类型的推导。将 auto 置于函数返回类型位置即可:
auto add(int x, int y)
{
    return x + y;   // 返回 int,编译器推导出返回类型为 int
}
使用 auto 返回类型时,函数内所有 return 语句必须返回相同类型,否则报错:
auto someFcn(bool b)
{
    if (b)
        return 5;    // int
    else
        return 6.7;  // double
}                    // 错误:返回类型不一致
若确实需要不同返回类型,可:
- 显式指定返回类型,让编译器做隐式转换;或
- 用 static_cast把所有返回值显式转成同一类型。上例可把5改为5.0,或用static_cast<double>(5)。
返回类型推导的优点
最大优势是消除返回类型不匹配的风险(避免意外转换)。
- 当返回类型极易随实现变动(脆弱返回类型)时,显式写死返回类型意味着每次实现变动都要同步修改,而 auto可自动适应。
- 若返回类型冗长或不易书写,auto可简化声明:我们将在 —— 多模板类型函数模板 中进一步讨论此类场景。// 让编译器推导 unsigned short + char 的结果类型 auto add(unsigned short x, char y) { return x + y; }
返回类型推导的缺点
- 必须先定义完整函数体,才能调用。前向声明不足! - auto foo(); // 仅前向声明 int main() { std::cout << foo(); // 错误:编译器无法推导返回类型 } auto foo() { return 5; }- 报类似错误: - error C3779: 'foo': 返回 'auto' 的函数必须定义后才能使用- 因此,返回 - auto的普通函数通常只能在定义所在文件内调用。
- 接口不明确:函数声明不显示返回类型,IDE 可提示,但无 IDE 时需查看实现才能知晓。接口类型的清晰性通常更重要。 
综上,一般应避免返回类型推导。
最佳实践
优先使用显式返回类型,除非返回类型不重要、难以书写或极易变动。
尾随返回类型语法
auto 也可用于尾随返回类型(trailing return type):
int add(int x, int y)
{
    return x + y;
}
// 等价写法
auto add(int x, int y) -> int
{
    return x + y;
}
此时 auto 不执行任何推导,仅构成语法的一部分。
使用场景:
- 复杂返回类型:// 传统写法难读 std::common_type_t<int, double> compare(int, double); // 尾随写法易读 auto compare(int, double) -> std::common_type_t<int, double>;
- 对齐函数名,提高连续声明可读性:auto add(int x, int y) -> int; auto divide(double x, double y) -> double; auto printSomething() -> void; auto generateSubstring(const std::string& s, int start, int len) -> std::string;
供进阶读者
若返回类型需依赖形参类型,传统写法无法使用形参名;尾随写法可用 decltype:
#include <type_traits>
// 非法:编译器尚未见到 x, y
std::common_type_t<decltype(x), decltype(y)> add(int x, double y);
// 合法
auto add(int x, double y)
    -> std::common_type_t<decltype(x), decltype(y)>;
Lambda 表达式也要求尾随语法。 目前建议:除必需场景,仍使用传统返回类型语法。
函数参数不支持类型推导
许多新手写出:
void addAndPrint(auto x, auto y)
{
    std::cout << x + y << '\n';
}
在 C++20 之前,上述代码无法编译(错误:形参不能使用 auto)。
C++20 起,该写法可通过编译,但这里的 auto 并非类型推导,而是触发了函数模板机制。
相关内容
auto 在函数模板中的使用见多模板类型函数模板。
