命名空间
变体
操作

return 语句

来自 cppreference.cn
< cpp‎ | 语言
 
 
C++ 语言
 
 

终止当前函数并将指定值(如果有)返回给调用者。

目录

[编辑] 语法

attr (可选) return expression (可选) ; (1)
attr (可选) return braced-init-list ; (2) (C++11 起)
attr (可选) co_return expression (可选) ; (3) (C++20 起)
attr (可选) co_return braced-init-list ; (4) (C++20 起)
属性 - (C++11 起) 任意数量的属性序列
表达式 - 表达式,可转换为函数返回类型
braced-init-list - 用花括号括起来的初始化列表

[编辑] 解释

1) 评估 expression,终止当前函数并将 expression 的结果(经过向函数返回类型的隐式转换后)返回给调用者。expression 在返回类型为 (可能是 cv-qualified) void 的函数中是可选的,在构造函数和析构函数中则不允许。
2) 使用复制列表初始化来构造函数的返回值。
3,4) 在协程中,对于最终挂起点必须使用关键字 co_return 而不是 return(详情请参阅协程)。

在函数调用结果的复制初始化和 expression 结束时所有临时对象的销毁之间有一个序列点

(C++11 前)

函数调用结果的复制初始化先于 expression 结束时所有临时对象的销毁进行,而临时对象的销毁又先于包含 return 语句的块的局部变量的销毁进行。

(C++11 起)

如果函数的返回类型是引用类型,并且 return 语句 (1,2) 将返回的引用绑定到临时表达式的结果,则程序格式错误。

(C++26 起)

如果控制流到达以下函数的末尾

  • 返回类型为 (可能是 cv-qualified) void 的函数,
  • 构造函数,
  • 析构函数,或者
  • 返回类型为 (可能是 cv-qualified) void函数 try

而没有遇到 return 语句,则执行 return;

如果控制流到达main 函数的末尾,则执行 return 0;

除了 main 函数和特定的协程(C++20 起) 之外,值返回函数在没有 return 语句的情况下执行到末尾是未定义行为。

在返回 (可能是 cv-qualified) void 的函数中,如果表达式类型是 (可能是 cv-qualified) void,则可以使用带 expression 的 return 语句。

如果函数的返回类型指定为占位符类型,它将从返回值推导

(C++14 起)

[编辑] 注意

按值返回可能涉及临时对象的构造和复制/移动,除非使用复制省略。具体来说,复制/移动的条件如下:

从局部变量和参数的自动移动

如果 expression 是一个(可能是带括号的)标识符表达式,它命名了一个具有自动存储持续时间且类型为:

  • 非 volatile 对象类型
(C++11 起)
  • 或非 volatile 右值引用对象类型
(C++20 起)

且该变量声明在

  • 最内层包围函数或 lambda 表达式的函数体中
  • 或作为其参数

的变量,则 expression 是*可移动的*。

(C++11 起)

如果 expression 是可移动的,用于选择构造函数以初始化返回值或,对于 co_return,用于选择 promise.return_value() 的重载(C++20 起)重载决议将执行*两次*:

  • 首先,就好像 expression 是一个右值表达式(因此它可能选择移动构造函数),并且
  • 如果第一次重载决议失败
(C++11 起)
(直至 C++23)
  • 或者成功了,但没有选择移动构造函数(形式上,所选构造函数的第一个参数不是对 expression 的(可能是 cv-qualified)类型的右值引用)
(C++11 起)
(C++20 前)
  • 则按照通常的方式执行重载决议,将 expression 视为左值(因此它可能选择复制构造函数)。
(C++11 起)
(直至 C++23)

如果 expression 是可移动的,则将其视为 xvalue(因此重载决议可能选择移动构造函数)。

(C++23 起)

保证的复制省略

如果 expression 是一个纯右值,则结果对象由该表达式直接初始化。当类型匹配时,这不涉及复制或移动构造函数(参阅复制省略)。

(C++17 起)
功能测试宏 标准 特性
__cpp_implicit_move 202207L (C++23) 隐式移动的简化

[编辑] 关键字

return, co_return

[编辑] 示例

#include <iostream>
#include <string>
#include <utility>
 
void fa(int i)
{
    if (i == 2)
        return;
    std::cout << "fa("<< i << ")\n";
} // implied return;
 
int fb(int i)
{
    if (i > 4)
        return 4;
    std::cout << "fb(" << i << ")\n";
    return 2;
}
 
std::pair<std::string, int> fc(const char* p, int x)
{
    return {p, x};
}
 
void fd()
{
    return fa(10); // fa(10) is a void expression
}
 
int main()
{
    fa(1); // prints its argument, then returns
    fa(2); // does nothing when i == 2, just returns
 
    int i = fb(5); // returns 4
    i = fb(i);     // prints its argument, returns 2
    std::cout << "i = " << i << '\n'
              << "fc(~).second = " << fc("Hello", 7).second << '\n';
 
    fd();
}
 
struct MoveOnly
{
    MoveOnly() = default;
    MoveOnly(MoveOnly&&) = default;
};
 
MoveOnly move_11(MoveOnly arg)
{
    return arg; // OK. implicit move
}
 
MoveOnly move_11(MoveOnly&& arg)
{
    return arg; // OK since C++20. implicit move
}
 
MoveOnly&& move_23(MoveOnly&& arg)
{
    return arg; // OK since C++23. implicit move
}

输出

fa(1)
fb(4)
i = 2
fc(~).second = 7
fa(10)

[编辑] 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 发布时的行为 正确的行为
CWG 1541 C++98 如果返回类型是 cv-qualified void,则 expression 不能省略 它可以省略
CWG 1579 C++11 不允许通过转换移动构造函数返回 允许转换移动
构造函数查找
CWG 1885 C++98 自动变量销毁的顺序不明确 添加了排序规则

[编辑] 另请参阅

C 文档 关于 return 语句