命名空间
变体
操作

return 语句

来自 cppreference.com
< cpp‎ | language
 
 
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 起)
attr - (自 C++11 起) 任意数量的 属性 序列
表达式 - 表达式,可转换为函数返回类型
braced-init-list - 大括号括起来的初始化列表

[编辑] 解释

1) 求值 expression,终止当前函数并将 expression 的结果返回给调用者,在 隐式转换 为函数返回类型后。在返回类型为(可能为 cv 限定的)void 的函数中,expression 是可选的,在构造函数和析构函数中是不允许的。
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,可以使用带有 表达式 的 return 语句。

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

(自 C++14 起)

[编辑] 注意

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

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

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

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

并且该变量在以下位置声明:

  • 在主体中,或
  • 作为参数
在最内层封闭函数或 lambda 表达式中。

如果 表达式 是可移动的,用于初始化返回值的构造函数的 重载解析或,对于 co_return,选择 promise.return_value() 的重载(自 C++20 起) 会执行 两次 

  • 首先,就像 表达式 是一个右值表达式一样(因此它可能会选择 移动构造函数),然后
  • 如果第一次重载解析失败,或者
  • 它成功了,但没有选择 移动构造函数(正式地,所选构造函数的第一个参数不是对 表达式 的(可能经过 cv 限定的)类型的右值引用)
(直到 C++20)
  • 然后,像往常一样执行重载解析,将 表达式 视为左值(因此它可能会选择 复制构造函数)。
(直到 C++23)

如果 表达式 是可移动的,它将被视为一个右值(因此重载解析可能会选择 移动构造函数)。

(自 C++23 起)
(自 C++11 起)

保证复制省略

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

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

[编辑] 关键词

returnco_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表达式 无法省略 可以省略
CWG 1579 C++11 通过转换移动构造函数返回是不允许的 转换移动
构造函数查找已启用
CWG 1885 C++98 自动变量的销毁顺序没有明确说明 添加了排序规则

[编辑] 另请参阅

C 文档 用于 return 语句