return
statement
Завершает текущую функцию и возвращает указанное значение (если есть) вызывающей стороне.
Содержание |
Синтаксис
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 | - | (since C++11) последовательность любого количества attributes |
| expression | - | expression , преобразуемая в тип возвращаемого значения функции |
| braced-init-list | - | brace-enclosed initializer list |
Объяснение
Выражение expression или braced-init-list (начиная с C++11) (если присутствует) называется операндом оператора return .
|
Существует точка следования между копирующей инициализацией результата вызова функции и уничтожением всех временных объектов в конце выражения . |
(до C++11) |
|
Копирующая инициализация результата вызова функции упорядочена перед уничтожением всех временных объектов в конце выражения , которое, в свою очередь, упорядочено перед уничтожением локальных переменных блока, содержащего оператор return . |
(начиная с C++11) |
|
Если возвращаемый тип функции является ссылочным типом и оператор return (1,2) связывает возвращаемую ссылку с результатом временного выражения , программа является некорректной. |
(начиная с C++26) |
Если управление достигает конца
- функция с возвращаемым типом (возможно, cv-квалифицированным) void ,
- конструктор,
- деструктор, или
- блок try функции для функции с возвращаемым типом (возможно, cv-квалифицированным) void
без встречи с оператором return , выполняется return ; .
Если управление достигает конца
main
функции
,
return
0
;
выполняется.
Выход за пределы возвращающей значение функции, за исключением функции
main
и определённых
корутин
(начиная с C++20)
, без оператора
return
является неопределённым поведением.
В функции, возвращающей (возможно, cv-квалифицированный) void , инструкция return с выражением может использоваться, если тип выражения является (возможно, cv-квалифицированным) void .
|
Если возвращаемый тип функции указан как тип-заполнитель , он будет выведен из возвращаемого значения. Если используется decltype ( auto ) , вывод типа трактует выражение , которое может быть сущностью , как сущность . |
(начиная с C++14) |
Примечания
Возврат по значению может включать создание и копирование/перемещение временного объекта, если не используется copy elision . Конкретно условия для копирования/перемещения следующие:
Автоматическое перемещение из локальных переменных и параметровВыражение является подходящим для перемещения , если это (возможно, заключенное в скобки) выражение-идентификатор , которое обозначает переменную с автоматической продолжительностью хранения, чей тип является
|
(since C++11) |
|
(since C++20) |
|
и эта переменная объявлена
самой внутренней охватывающей функции или лямбда-выражения. |
(since C++11) |
|
Если выражение подходит для перемещения, разрешение перегрузки для выбора конструктора, используемого для инициализации возвращаемого значения или, для co_return , для выбора перегрузки promise. return_value ( ) (since C++20) выполняется дважды :
|
(since C++11)
(until C++23) |
|
(since C++11)
(until C++20) |
|
(since C++11)
(until C++23) |
|
Если выражение подходит для перемещения, оно рассматривается как xvalue (таким образом, разрешение перегрузки может выбрать move constructor ). |
(since C++23) |
Гарантированное пропускание копированияЕсли выражение является prvalue, результирующий объект инициализируется непосредственно этим выражением. Это не включает copy constructor или move constructor, когда типы совпадают (см. copy elision ). |
(since 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"; } // неявный возврат; 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) является void-выражением } int main() { fa(1); // выводит аргумент, затем возвращает fa(2); // ничего не делает при i == 2, просто возвращает int i = fb(5); // возвращает 4 i = fb(i); // выводит аргумент, возвращает 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. неявное перемещение } MoveOnly move_11(MoveOnly&& arg) { return arg; // OK начиная с C++20. неявное перемещение } MoveOnly&& move_23(MoveOnly&& arg) { return arg; // OK начиная с C++23. неявное перемещение }
Вывод:
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
инструкции
|