命名空間
變體
動作

return 陳述式

出自 cppreference.com
< 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 起)
屬性 - (since C++11) 任意數量的 屬性序列
expression - expression,可轉換為函數返回類型
braced-init-list - 大括號包圍的初始化列表

[編輯] 解釋

1) 計算 expression,終止當前函數,並在進行隱式轉換為函數返回類型後,將 expression 的結果返回給呼叫者。對於返回類型為(可能經 cv 限定的)void 的函數,expression 是可選的,而在建構函數與解構函數中則不允許使用。
2) 使用列表初始化 (copy-list-initialization) 來建構函數的返回值。
3,4) 在協程 (coroutine) 中,最後的暫停點必須使用關鍵字 co_return 而非 return(詳情請見協程)。

在函數呼叫結果的拷貝初始化,與 expression 結尾處所有暫時物件的解構之間,存在一個序列點 (sequence point)

(直到 C++11)

函數呼叫結果的拷貝初始化,定序於 (sequenced-before) expression 結尾處所有暫時物件的解構之前;而這些解構,又定序於包含該 return 陳述式的區塊中局部變數的解構之前。

(C++11 起)

如果函數的返回類型是參考類型,且 return 陳述式 (1,2) 將返回的參考繫結至暫時運算式 (temporary expression) 的結果,則程式格式錯誤。

(C++26 起)

如果控制流到達以下位置的末尾:

  • 返回類型為(可能經 cv 限定的)void 的函數,
  • 建構函數,
  • 解構函數,或
  • 返回類型為(可能經 cv 限定的)void 的函數之函數 try 區塊

且未遇到 return 陳述式,則執行 return;

如果控制流到達 main 函數 的末尾,則執行 return 0;

除了 main 函數及特定協程(C++20 起)外,若在有返回值的函數結尾處流出且沒有 return 陳述式,則屬於未定義行為。

在返回(可能經 cv 限定的)void 的函數中,如果運算式的類型也是(可能經 cv 限定的)void,則可以使用帶有 expression 的 return 陳述式。

如果函數的返回類型被指定為佔位符類型 (placeholder type),它將根據返回值進行推導

(C++14 起)

[編輯] 附註

按值返回可能涉及暫時物件的建構與拷貝/移動,除非使用拷貝省略 (copy elision)。具體來說,拷貝/移動的條件如下:

從局部變數與參數進行自動移動

expression 是一個(可能被括號括起來的)識別符運算式,且該識別符命名了一個具有自動儲存期的變數,且其類型為:

  • 非 volatile 的物件類型
(C++11 起)
  • 或非 volatile 的物件類型右值參考
(自 C++20 起)

且該變數宣告於:

  • 函數體內
  • 或作為參數

(且該函數或 lambda 表達式為最內層的包裹作用域),則稱該 expression可移動 (move-eligible)

(C++11 起)

如果 expression 是可移動的,則會進行兩次重載決議 (overload resolution),以選擇用於初始化返回值的建構函數,或者對於 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 是一個純右值 (prvalue),結果物件會直接由該運算式初始化。在類型匹配時,這不涉及任何拷貝或移動建構函數(請參見拷貝省略)。

(自 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++ 標準。

DR 應用於 出版時的行為 正確的行為
CWG 1541 C++98 如果返回類型為 cv 限定的 void,則 expression 不可省略 此情況下可省略
CWG 1579 C++11 不允許透過轉換移動建構函數返回 啟用轉換移動
建構函數查找
CWG 1885 C++98 自動變數解構的定序不明確 添加定序規則

[編輯] 參見

C 語言文件 關於 return 陳述式
取自 "https://cppreference.tw/mwiki/index.php?title=cpp/language/return&oldid=181050"
English Deutsch 日本語 한국어 中文(简体) 中文(繁體)