return инструкция
Завершает текущую функцию и возвращает вызывающей стороне указанное значение (если оно есть).
Синтаксис
attr (optional) return expression (optional) ; | (1) | |
attr (optional) return braced-init-list ; | (2) | (с C++11) |
attr (optional) co_return expression (optional) ; | (3) | (с C++20) |
attr (optional) co_return braced-init-list ; | (4) | (с C++20) |
| attr | - | (с C++11) последовательность из любого количества атрибутов |
| expression | - | выражение, преобразуемое в тип возвращаемого значения функции |
| braced-init-list | - | список инициализаторов в фигурных скобках |
Пояснение
co_return вместо return (подробности см. в разделе «Сопрограммы»).expression или braced-init-list(с C++11) (если есть) называется операндом инструкции return.
| Между копирующей инициализацией результата вызова функции и уничтожением всех временных объектов в конце expression имеется точка следования. | (до C++11) |
| Копирующая инициализация результата вызова функции упорядочена перед уничтожением всех временных объектов в конце expression, которое, в свою очередь, упорядочено перед уничтожением локальных переменных блока, содержащего инструкцию return. | (с C++11) |
| Если возвращаемый тип функции является ссылочным типом, а инструкция return (1,2) связывает возвращаемую ссылку с результатом временного выражения, программа некорректна. | (с C++26) |
Если управление достигает конца
- функции с типом возвращаемого значения (возможно, cv-квалифицированным) void,
- конструктора,
- деструктора или
- блока try функции с типом возвращаемого значения (возможно, cv-квалифицированным) void
и при этом не встречает инструкцию return, выполняется return;.
Если управление достигает конца функции main, выполняется return 0;.
Достижение конца функции, возвращающей значение, без инструкции return приводит к неопределённому поведению, за исключением функции main и некоторых сопрограмм(с C++20).
В функции, возвращающей (возможно, cv-квалифицированный) void, можно использовать инструкцию return с expression, если тип выражения — (возможно, cv-квалифицированный) void.
| Если возвращаемый тип функции задан как тип-заполнитель, он будет выведен из возвращаемого значения. При использовании decltype(auto) при выводе типа expression, которое может быть entity, рассматривается как entity. | (с C++14) |
Примечания
Возврат по значению может повлечь создание временного объекта, а также его копирование или перемещение, если не используется устранение копирования. Условия копирования и перемещения описаны ниже.
Автоматическое перемещение локальных переменных и параметровexpression допускает перемещение, если оно является (возможно, заключённым в скобки) выражением-идентификатором, обозначающим переменную с автоматической длительностью хранения, тип которой представляет собой
| (с C++11) |
| (с C++20) |
| и эта переменная объявлена
ближайшей охватывающей функции или лямбда-выражения. | (с C++11) |
| Если expression допускает перемещение, разрешение перегрузки для выбора конструктора, используемого при инициализации возвращаемого значения или для выбора перегрузки
|
(с 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++.
| Отчёт об ошибке | Применён к | Опубликованное поведение | Корректное поведение |
|---|---|---|---|
| CWG 1541 | C++98 | expression нельзя было опустить, если возвращаемый тип был cv-квалифицированным void | его можно опустить |
| CWG 1579 | C++11 | возврат с помощью преобразующего конструктора перемещения был запрещён | поиск преобразующего конструктора перемещения разрешён |
| CWG 1885 | C++98 | порядок уничтожения автоматических переменных не был явно определён | добавлены правила упорядочивания |
См. также
Документация по C для инструкции return |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/return