return 陳述式
終止當前函數,並將指定的值(若有的話)返回給呼叫者。
目錄 |
[編輯] 語法
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 | - | 大括號包圍的初始化列表 |
[編輯] 解釋
|
在函數呼叫結果的拷貝初始化,與 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 是一個(可能被括號括起來的)識別符運算式,且該識別符命名了一個具有自動儲存期的變數,且其類型為:
|
(C++11 起) |
|
(自 C++20 起) |
|
且該變數宣告於:
(且該函數或 lambda 表達式為最內層的包裹作用域),則稱該 expression 為可移動 (move-eligible)。 |
(C++11 起) |
|
如果 expression 是可移動的,則會進行兩次重載決議 (overload resolution),以選擇用於初始化返回值的建構函數,或者對於 co_return,選擇 promise.return_value() 的重載(C++20 起):
|
(C++11 起) (至 C++23 止) |
|
(C++11 起) (直到 C++20) |
|
(C++11 起) (至 C++23 止) |
|
如果 expression 是可移動的,它會被視為 xvalue(因此重載決議可能會選擇移動建構函數)。 |
(自 C++23 起) |
保證拷貝省略如果 expression 是一個純右值 (prvalue),結果物件會直接由該運算式初始化。在類型匹配時,這不涉及任何拷貝或移動建構函數(請參見拷貝省略)。 |
(自 C++17 起) |
| 特性測試巨集 | 數值 | 標準 | 功能 |
|---|---|---|---|
__cpp_implicit_move |
202207L |
(C++23) | 更簡單的隱式移動 |
[編輯] 關鍵字
[編輯] 範例
#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 陳述式 |