return c++ ejemplos
¿Qué significa "int & foo()" en C++? (9)
El código de ejemplo en la página vinculada es solo una declaración de función ficticia. No se compila, pero si tuviera alguna función definida, funcionaría en general. El ejemplo significaba "Si tuviera una función con esta firma, podría usarla así".
En su ejemplo,
foo
claramente está devolviendo un valor basado en la firma, pero usted devuelve un valor que se convierte en un valor.
Esto claramente está determinado a fallar.
Podrías hacerlo:
int& foo()
{
static int x;
return x;
}
y tendría éxito al cambiar el valor de x, al decir:
foo() = 10;
Mientras leía esta explicación sobre valores y valores, estas líneas de código me llamaron la atención:
int& foo();
foo() = 42; // OK, foo() is an lvalue
Lo probé en g ++, pero el compilador dice "referencia indefinida a foo ()". Si agrego
int foo()
{
return 2;
}
int main()
{
int& foo();
foo() = 42;
}
Se compila bien, pero ejecutarlo produce un error de segmentación . Solo la linea
int& foo();
por sí mismo compila y ejecuta sin ningún problema.
¿Qué significa este código? ¿Cómo puede asignar un valor a una llamada de función y por qué no es un valor r?
En ese contexto, & significa una referencia, por lo que foo devuelve una referencia a un int, en lugar de un int.
No estoy seguro de si hubieras trabajado con punteros todavía, pero es una idea similar, en realidad no estás devolviendo el valor de la función, sino que estás pasando la información necesaria para encontrar la ubicación en la memoria donde eso int es.
Entonces, para resumir, no está asignando un valor a una llamada de función: está utilizando una función para obtener una referencia y luego asigna el valor que se está haciendo referencia a un nuevo valor. Es fácil pensar que todo sucede a la vez, pero en realidad la computadora hace todo en un orden preciso.
Si se está preguntando, la razón por la que está obteniendo una segfault es porque está devolviendo un literal numérico ''2'', por lo que es el error exacto que obtendría si tuviera que definir una constante int y luego tratar de modificar su valor.
Si aún no ha aprendido sobre punteros y memoria dinámica, entonces lo recomendaría primero ya que hay algunos conceptos que creo que son difíciles de entender a menos que los esté aprendiendo todos a la vez.
La explicación es suponer que hay una implementación razonable para
foo
que devuelve una referencia de valor a un
int
válido.
Tal implementación podría ser:
int a = 2; //global variable, lives until program termination
int& foo() {
return a;
}
Ahora, dado que
foo
devuelve una referencia lvalue, podemos asignar algo al valor de retorno, de esta manera:
foo() = 42;
Esto actualizará la a global con el valor
42
, que podemos verificar accediendo a la variable directamente o llamando a
foo
nuevamente:
int main() {
foo() = 42;
std::cout << a; //prints 42
std::cout << foo(); //also prints 42
}
La función que tiene, foo (), es una función que devuelve una referencia a un entero.
Entonces, digamos que originalmente foo devolvió 5, y más tarde, en su función principal, usted dice
foo() = 10;
, luego imprime foo, imprimirá 10 en lugar de 5.
Espero que tenga sentido :)
Soy nuevo en programación también. ¡Es interesante ver preguntas como esta que te hacen pensar! :)
Todas las otras respuestas declaran una estática dentro de la función. Creo que eso podría confundirte, así que mira esto:
int& highest(int & i, int & j)
{
if (i > j)
{
return i;
}
return j;
}
int main()
{
int a{ 3};
int b{ 4 };
highest(a, b) = 11;
return 0;
}
Como el
highest()
devuelve una referencia, puede asignarle un valor.
Cuando esto se ejecute,
b
se cambiará a 11. Si cambió la inicialización de modo que
a
fuera, digamos, 8, entonces
a
se cambiaría a 11. Este es un código que en realidad podría tener un propósito, a diferencia de los otros ejemplos.
int & foo();
significa que
foo()
devuelve una referencia a una variable.
Considera este código:
#include <iostream>
int k = 0;
int &foo()
{
return k;
}
int main(int argc,char **argv)
{
k = 4;
foo() = 5;
std::cout << "k=" << k << "/n";
return 0;
}
Este código imprime:
$ ./a.out k = 5
Porque
foo()
devuelve una referencia a la variable global
k
.
En su código revisado, está convirtiendo el valor devuelto en una referencia, que luego no es válida.
int &foo();
declara una función llamada
foo()
con el tipo de retorno
int&
.
Si llama a esta función sin proporcionar un cuerpo, es probable que obtenga un error de referencia indefinido.
En su segundo intento, proporcionó una función
int foo()
.
Esto tiene un tipo de retorno diferente a la función declarada por
int& foo();
.
Por lo tanto, tiene dos declaraciones del mismo
foo
que no coinciden, lo que viola la Regla de una definición y causa un comportamiento indefinido (no se requiere diagnóstico).
Para algo que funciona, saque la declaración de función local. Pueden llevar a un comportamiento silencioso e indefinido, como ha visto. En su lugar, solo use declaraciones de funciones fuera de cualquier función. Su programa podría verse así:
int &foo()
{
static int i = 2;
return i;
}
int main()
{
++foo();
std::cout << foo() << ''/n'';
}
int& foo();
es una función que devuelve una referencia a
int
.
Su función proporcionada devuelve
int
sin referencia.
Puedes hacer
int& foo()
{
static int i = 42;
return i;
}
int main()
{
int& foo();
foo() = 42;
}
int& foo();
Declara una función llamada foo que devuelve una referencia a un
int
.
Lo que los ejemplos no pueden hacer es darle una definición de esa función que podría compilar.
Si usamos
int & foo()
{
static int bar = 0;
return bar;
}
Ahora tenemos una función que devuelve una referencia a
bar
.
Como la barra es
static
, seguirá viva después de la llamada a la función, por lo que devolver una referencia a ella es seguro.
Ahora si lo hacemos
foo() = 42;
Lo que sucede es que asignamos 42 a la
bar
ya que asignamos a la referencia y la referencia es solo un alias para la
bar
.
Si llamamos a la función nuevamente como
std::cout << foo();
Imprimiría 42 ya que establecemos una
bar
a la anterior.