Namespaces
Variants

return statement

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
goto - return
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Завершает текущую функцию и возвращает указанное значение (если есть) вызывающей стороне.

Содержание

Синтаксис

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

Объяснение

1) Вычисляет выражение , завершает текущую функцию и возвращает результат выражения вызывающей стороне после неявного преобразования к типу возвращаемого значения функции. Выражение является необязательным в функциях, возвращаемый тип которых — (возможно, cv-квалифицированный) void , и запрещено в конструкторах и деструкторах.
2) Использует copy-list-initialization для конструирования возвращаемого значения функции.
3,4) В сопрограмме ключевое слово co_return должно использоваться вместо return для точки финальной приостановки (см. сопрограммы для подробностей).

Выражение 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 . Конкретно условия для копирования/перемещения следующие:

Автоматическое перемещение из локальных переменных и параметров

Выражение является подходящим для перемещения , если это (возможно, заключенное в скобки) выражение-идентификатор , которое обозначает переменную с автоматической продолжительностью хранения, чей тип является

  • не-volatile объектным типом
(since C++11)
  • или не-volatile rvalue-ссылкой на объектный тип
(since C++20)

и эта переменная объявлена

  • в теле
  • или как параметр

самой внутренней охватывающей функции или лямбда-выражения.

(since C++11)

Если выражение подходит для перемещения, разрешение перегрузки для выбора конструктора, используемого для инициализации возвращаемого значения или, для co_return , для выбора перегрузки promise. return_value ( ) (since C++20) выполняется дважды :

  • сначала как если бы выражение было rvalue-выражением (таким образом, может быть выбран move constructor ), и
  • если первое разрешение перегрузки завершилось неудачей
(since C++11)
(until C++23)
  • или оно завершилось успешно, но не выбрало move constructor (формально, первый параметр выбранного конструктора не был rvalue-ссылкой на (возможно, cv-квалифицированный) тип выражения )
(since C++11)
(until C++20)
  • затем разрешение перегрузки выполняется как обычно, с выражением , рассматриваемым как lvalue (таким образом, может быть выбран copy constructor ).
(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) Упрощённое неявное перемещение

Ключевые слова

return , co_return

Пример

#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 инструкции