命名空间
变体
操作

return 语句

来自 cppreference.cn
< cpp‎ | language
 
 
C++ 语言
通用主题
流程控制
条件执行语句
if
迭代语句(循环)
for
范围 for (C++11)
跳转语句
goto - return
函数
函数声明
Lambda 函数表达式
inline 说明符
动态异常规范 (直到 C++17*)
noexcept 说明符 (C++11)
异常
命名空间
类型
说明符
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
存储期说明符
初始化
 
 

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

目录

[编辑] 语法

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 起)
attr - (自 C++11 起) 任意数量的 属性 序列
expression - expression,可转换为函数返回类型
braced-init-list - 花括号包围的初始化器列表

[编辑] 解释

1) 求值 expression,终止当前函数,并将 expression 的结果在隐式转换为函数返回类型后返回给调用者。expression 在返回类型为(可能带 cv 限定的)void 的函数中是可选的,并且在构造函数和析构函数中是不允许的。
2) 使用复制列表初始化来构造函数的返回值。
3,4) 在协程中,关键词 co_return 必须用于代替 return 以表示最终挂起点(详情见 协程)。

在函数调用的结果的复制初始化与在 expression 结尾所有临时对象的销毁之间存在顺序点

(直到 C++11)

函数调用的结果的复制初始化先于expression 结尾所有临时对象的销毁,而后者先于包围 return 语句的块的局部变量的销毁。

(自 C++11 起)

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

(自 C++26 起)

如果控制流到达结尾

  • 返回类型为(可能带 cv 限定的)void 的函数,
  • 构造函数,
  • 析构函数,或
  • 返回类型为(可能带 cv 限定的)void 的函数的函数 try

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

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

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

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

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

(自 C++14 起)

[编辑] 注解

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

从局部变量和形参自动移动

如果 expression 是(可能带括号的)标识符表达式,它命名一个具有自动存储期的变量,且该变量的类型是

  • 非易失对象类型
(自 C++11 起)
  • 或非易失到对象类型的右值引用
(自 C++20 起)

并且该变量被声明在

  • 最内层封闭函数或 lambda 表达式的
  • 函数体中

或作为形参。

(自 C++11 起)

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

  • 第一次如同 expression 是一个右值表达式(因此它可能选择移动构造函数),并且
  • 如果第一次重载决议失败
(自 C++11 起)
(直到 C++23)
  • 或者它成功了,但没有选择移动构造函数(形式上,所选构造函数的第一个形参不是到 expression 的(可能带 cv 限定的)类型的右值引用)
(自 C++11 起)
(直到 C++20)
  • 则像往常一样执行重载决议,将 expression 视为左值(因此它可能选择复制构造函数)。
(自 C++11 起)
(直到 C++23)

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

(自 C++23 起)

保证复制省略

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

(自 C++17 起)
特性测试宏 Std 特性
__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++ 标准。

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

[编辑] 参见

C 文档 关于 return 语句