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

Termina la función actual y devuelve el valor especificado (si lo hay) al llamador.

Contenidos

Sintaxis

attr  (opcional) return expresión  (opcional) ; (1)
attr  (opcional) return lista-de-inicialización-entre-llaves ; (2) (desde C++11)
attr  (opcional) co_return expresión  (opcional) ; (3) (desde C++20)
attr  (opcional) co_return lista-de-inicialización-entre-llaves ; (4) (desde C++20)
attr - (since C++11) secuencia de cualquier número de atributos
expression - expresión , convertible al tipo de retorno de la función
braced-init-list - lista de inicializadores entre llaves

Explicación

1) Evalúa la expresión , termina la función actual y devuelve el resultado de la expresión al llamador, después de conversión implícita al tipo de retorno de la función. La expresión es opcional en funciones cuyo tipo de retorno es (posiblemente calificado cv) void , y está prohibida en constructores y destructores.
2) Utiliza copy-list-initialization para construir el valor de retorno de la función.
3,4) En una corrutina, la palabra clave co_return debe utilizarse en lugar de return para el punto de suspensión final (consulte coroutines para más detalles).

La expresión o lista-de-inicialización-entre-llaves (desde C++11) (si existe) se conoce como el operando de la sentencia return .

Existe un punto de secuencia entre la inicialización por copia del resultado de la llamada a la función y la destrucción de todos los temporales al final de la expresión .

(hasta C++11)

La inicialización por copia del resultado de la llamada a la función está secuenciada-antes de la destrucción de todos los temporales al final de la expresión , que, a su vez, está secuenciada-antes de la destrucción de las variables locales del bloque que encierra la sentencia return .

(desde C++11)

Si el tipo de retorno de la función es un tipo referencia y una sentencia return (1,2) vincula la referencia retornada al resultado de una expresión temporal , el programa está mal formado.

(desde C++26)

Si el control llega al final de

  • una función con el tipo de retorno (posiblemente calificado cv) void ,
  • un constructor,
  • un destructor, o
  • un bloque try de función para una función con el tipo de retorno (posiblemente calificado cv) void

sin encontrar una return statement, return ; se ejecuta.

Si el control alcanza el final de la main función , return 0 ; se ejecuta.

Salir del final de una función que retorna un valor, excepto la función main y ciertas corrutinas (desde C++20) , sin una sentencia return es comportamiento indefinido.

En una función que retorna (posiblemente calificado con cv) void , la sentencia return con expresión puede ser utilizada, si el tipo de la expresión es (posiblemente calificado con cv) void .

Si el tipo de retorno de una función se especifica como un tipo de marcador de posición , será deducido a partir del valor de retorno. Si se utiliza decltype ( auto ) , la deducción de tipos trata una expresión que puede ser una entidad como una entidad .

(desde C++14)

Notas

Retornar por valor puede involucrar la construcción y copia/traslado de un objeto temporal, a menos que se utilice copy elision . Específicamente, las condiciones para copia/traslado son las siguientes:

Movimiento automático desde variables locales y parámetros

La expresión es elegible para movimiento si es una expresión de identificador (posiblemente entre paréntesis) que nombra una variable de duración de almacenamiento automático cuyo tipo es

  • un tipo objeto no volátil
(desde C++11)
  • o una referencia a valor derecho no volátil a tipo objeto
(desde C++20)

y esa variable está declarada

  • en el cuerpo
  • o como un parámetro

de la función o expresión lambda envolvente más interna.

(desde C++11)

Si la expresión es elegible para movimiento, la resolución de sobrecarga para seleccionar el constructor a usar para la inicialización del valor devuelto o, para co_return , para seleccionar la sobrecarga de promise. return_value ( ) (desde C++20) se realiza dos veces :

  • primero como si la expresión fuera una expresión de valor derecho (por lo tanto puede seleccionar el constructor de movimiento ), y
  • si la primera resolución de sobrecarga falló
(desde C++11)
(hasta C++23)
  • o tuvo éxito, pero no seleccionó el constructor de movimiento (formalmente, el primer parámetro del constructor seleccionado no era una referencia a valor derecho al tipo (posiblemente calificado cv) de expresión )
(desde C++11)
(hasta C++20)
  • entonces la resolución de sobrecarga se realiza normalmente, con la expresión considerada como un valor izquierdo (por lo que puede seleccionar el constructor de copia ).
(desde C++11)
(hasta C++23)

Si la expresión es elegible para movimiento, se trata como un valor x (por lo tanto la resolución de sobrecarga puede seleccionar el constructor de movimiento ).

(desde C++23)

Eliminación de copia garantizada

Si la expresión es un valor pr, el objeto resultado se inicializa directamente por esa expresión. Esto no implica un constructor de copia o movimiento cuando los tipos coinciden (ver eliminación de copia ).

(desde C++17)
Macro de prueba de características Valor Std Característica
__cpp_implicit_move 202207L (C++23) Movimiento implícito más simple

Palabras clave

return , co_return

Ejemplo

#include <iostream>
#include <string>
#include <utility>
void fa(int i)
{
    if (i == 2)
        return;
    std::cout << "fa("<< i << ")\n";
} // retorno implícito;
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) es una expresión void
}
int main()
{
    fa(1); // imprime su argumento, luego retorna
    fa(2); // no hace nada cuando i == 2, solo retorna
    int i = fb(5); // retorna 4
    i = fb(i);     // imprime su argumento, retorna 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. movimiento implícito
}
MoveOnly move_11(MoveOnly&& arg)
{
    return arg; // OK desde C++20. movimiento implícito
}
MoveOnly&& move_23(MoveOnly&& arg)
{
    return arg; // OK desde C++23. movimiento implícito
}

Salida:

fa(1)
fb(4)
i = 2
fc(~).second = 7
fa(10)

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares publicados anteriormente de C++.

DR Se aplica a Comportamiento publicado Comportamiento correcto
CWG 1541 C++98 expresión no podía omitirse si el tipo de retorno es cv-calificado void puede omitirse
CWG 1579 C++11 no se permitía el retorno mediante constructor de movimiento de conversión búsqueda de constructor de movimiento
de conversión habilitada
CWG 1885 C++98 la secuenciación de la destrucción de variables automáticas no era explícita reglas de secuenciación añadidas

Véase también

Documentación de C para return statement