resueltos - get y set c++ ejemplos
C++-devuelve x, y; ¿Cual es el punto? (18)
Si y siempre se devuelve sin embargo, entonces ¿cuál es el punto?
El punto es el efecto secundario de x (es decir, del lado izquierdo del operador de coma). Ver, por ejemplo, la respuesta de Justin Ethier para más detalles.
¿Hay un caso en el que una declaración de devolución deba crearse así?
Un ejemplo es para una función constexpr en C ++ 11 hasta C ++ 14: tal función puede no contener declaraciones arbitrarias, sino exactamente una declaración de retorno.
Aquí hay un ejemplo de código de Patrice Roys "La situación de excepción" en CppCon 2016 :
constexpr int integral_div(int num, int denom) {
return assert(denom != 0), num / denom;
}
He estado programando en C y C ++ durante algunos años y ahora estoy tomando un curso universitario y nuestro libro tuvo una función como esta para un ejemplo:
int foo(){
int x=0;
int y=20;
return x,y; //y is always returned
}
Nunca he visto tal sintaxis. De hecho, nunca he visto el operador utilizado fuera de las listas de parámetros. Si y
siempre se devuelve sin embargo, entonces ¿cuál es el punto? ¿Hay un caso en el que una declaración de devolución deba crearse así?
(Además, etiqueté C también porque se aplica a ambos, aunque mi libro específicamente es C ++)
¿Hay un caso en el que una declaración de devolución deba crearse así?
En mi opinión, nunca usaría múltiples devoluciones en una función como el ejemplo de libro. Viola el diseño estructurado. Sin embargo, hay muchos programadores que lo hacen! Depurando el código de otra persona, le asigné un valor a una variable global en cada declaración de devolución para poder averiguar qué devolución se ejecutó.
Al igual que todos los que comentan aquí piensan que no tiene sentido y no estoy en desacuerdo, solo mirando el ejemplo, voy a hacer una conjetura que no es mucho mejor:
El escritor estaba recibiendo una advertencia del compilador acerca de que x no se usaba dentro de la función, y esta era una manera fácil de hacer que la advertencia desapareciera.
Cuando se usa con la palabra clave return
, el operador de coma devuelve el último valor, que inicialmente es confuso pero puede hacer las cosas más concisas .
Por ejemplo, el siguiente programa saldrá con un código de estado de 2.
#include <iostream>
using namespace std;
void a() {
cout << "a" << endl;
}
int one() {
cout << "one" << endl;
return 1;
}
int zero() {
cout << "zero" << endl;
return 0;
}
int main() {
return one(), a(), zero(), 2;
}
Al compilar y ejecutar con lo siguiente, verá la salida a continuación.
michael$ g++ main.cpp -o main.out && ./main.out ; echo $?
one
a
zero
2
De acuerdo con la C FAQ :
Precisamente, el significado del operador de coma en la expresión general
e1, e2
es "evaluar la subexpresión e1, luego evaluar e2; el valor de la expresión es el valor de e2". Por lo tanto, e1 debería implicar una asignación o un incremento ++ o una disminución, o una llamada a la función o algún otro tipo de efecto secundario, porque de lo contrario se calcularía un valor que se descartaría.
Así que estoy de acuerdo con usted, no hay otro punto más que ilustrar que esta es una sintaxis válida, si eso.
Si desea devolver ambos valores en C o C ++, puede crear una struct
contenga los miembros x
e y
, y en su lugar, devolver la estructura:
struct point {int x; int y;};
Luego, puede definir un tipo y una función auxiliar para permitirle devolver fácilmente ambos valores dentro de la struct
:
typedef struct point Point;
Point point(int xx, int yy){
Point p;
p.x = xx;
p.y = yy;
return p;
}
Y luego cambie su código original para usar la función de ayuda:
Point foo(){
int x=0;
int y=20;
return point(x,y); // x and y are both returned
}
Y por último, puedes probarlo:
Point p = foo();
printf("%d, %d/n", p.x, p.y);
Este ejemplo compila tanto en C como en C ++. Aunque, como sugiere Mark a continuación, en C ++ puede definir un constructor para la estructura de point
que ofrezca una solución más elegante.
En una nota al margen, la capacidad de devolver múltiples valores directamente es maravillosa en idiomas como Python que lo admiten:
def foo():
x = 0
y = 20
return x,y # Returns a tuple containing both x and y
>>> foo()
(0, 20)
El libro está tratando de eliminar la posible confusión de las personas que aprendieron otros idiomas antes de C ++. En muchos idiomas, puede devolver varios valores utilizando una sintaxis similar. En C ++, se compilará sin previo aviso (a menos que especifique -Wall
o -Wunused-value
), pero no funcionará de la manera que podría esperar si estuviera acostumbrado a esos otros idiomas. Sólo devolverá el último valor.
Sin embargo, parece que el autor causó más confusión de la que evitó, ya que no hay una situación legible para usar dicha sintaxis en una declaración de retorno en C ++, excepto que se usa accidentalmente como en otro idioma. Está advirtiendo sobre el uso que no se le ocurriría a la mayoría de las personas intentar. Sin embargo, si lo hicieras, sería muy confuso depurar, ya que la instrucción de asignación múltiple int x, y = foo()
también compila bien.
En resumen: siempre use -Wall
y arregle lo que le advierte. La sintaxis de C ++ te permite escribir muchas cosas que no tienen sentido.
El operador de coma se usa principalmente en declaraciones como esta:
for( int i=0, j=10; i<10; i++, j++ )
{
a[i] = b[j];
}
La primera coma no es un operador de coma, es parte de la sintaxis de la declaración. El segundo es un operador de coma.
Eso parece un terrible ejemplo de código. Podría ser una sintaxis válida en C / C ++, pero no puedo pensar en una razón por la que alguna vez querrías hacer eso.
Si desea devolver tanto x como y, una mejor manera de hacerlo en C ++ sería definir una clase o estructura de "Punto" con propiedades x e y, y devolver eso. Otra opción sería pasar x e y por referencia, luego establecer los valores adecuadamente en el método.
Si el método solo va a devolver y, yo simplemente "devolvería y;". Si x necesita ser "evaluado" antes de la declaración de retorno, debe hacerse en una línea separada.
Esta sintaxis se puede usar para guardar paréntesis de alcance adicionales de una sentencia if
-. Por ejemplo, normalmente escribirías lo siguiente:
if (someThing == true)
{
a = 1;
b = 2;
return true;
}
Esto puede ser reemplazado por el siguiente:
if (someThing == true)
return a = 1, b = 2, true;
Creo que el uso de este estilo de codificación está más bien motivado por la necesidad de posar que por escribir código limpio.
Este es el operador de coma (,) .
Ambas expresiones xey son evaluadas. El resultado de la expresión general es y, es decir, el último valor.
Es difícil decir por qué se usa aquí. Supongo, para fines de demostración. Claramente la función podría ser refaccionada a:
int foo()
{
return 20;
}
Este es el operador de coma. Dicha sintaxis se puede usar para deshabilitar la advertencia del compilador sobre la variable x
no utilizada.
Esto realmente no responde a la pregunta original en absoluto, pero podría ser de interés para algunas personas, pero si quisiera que regresara con C ++, tendría que escribirlo de esta manera (y necesitaría un compilador de C ++ 0x )
tuple<int, int> foo()
{
int x = 0;
int y = 20;
return make_tuple(x, y);
}
El acceso es así.
tuple<int, int> data = foo();
int a = get<0>(data);
int b = get<1>(data);
Fuera de for loops, el otro usuario principal de este operador de comando (como se adjunta a la versión de llamada de función) está en macros que devuelven un valor después de hacer algunas cosas. Estas son otras formas de hacer esto ahora, pero creo que el operador de comando solía ser la forma más limpia.
#define next(A, x, y, M) ((x) = (++(y))%(M) , A[(x)])
Tenga en cuenta que esta macro es un mal ejemplo de macros en general porque se repite x y probablemente por otras razones. El uso del operador de coma de esta manera debería ser raro. El ejemplo de su libro fue probablemente un intento de hacer que un código se ajuste a la cantidad de líneas disponibles para ese ejemplo.
He visto esta sintaxis utilizada en C para realizar tareas de limpieza cuando regresa a mitad de camino en una operación. Definitivamente no es un código mantenible:
int foo(int y){
char *x;
x = (char*)malloc(y+1);
/** operations */
if (y>100) return free(x),y;
/** operations */
if (y>1000) return free(x),y;
}
La coma en las listas de parámetros solo está ahí para separar los parámetros, y no es lo mismo que el operador de coma. El operador de coma, como en tu ejemplo, evalúa tanto x como y, y luego tira x.
En este caso, supongo que es un error de alguien que intenta devolver dos valores y no sabía cómo hacerlo.
No hay ningún punto en esa declaración de retorno.
Si x
se declarara volatile
, forzaría un acceso (ya que al menos en C ++ las referencias a volatile
variables volatile
se consideran un comportamiento observable externamente), pero no lo es.
Si, en lugar de x
, hubiera algún tipo de cálculo con efectos secundarios, haría ese cálculo y luego devolvería y
. Sin embargo, una x
no volatile
no tiene efectos secundarios. No se requiere que la implementación ejecute ningún código que no tenga efectos secundarios o comportamiento observable externamente. El operador de coma ejecuta lo que esté en el lado izquierdo de la coma, ignora el resultado y ejecuta y mantiene el valor del lado derecho (excepto que es libre ignorar el lado izquierdo del operador en este caso).
Por lo tanto, el return x, y;
declaración es exactamente lo mismo que return y;
. Si x
no fuera solo una cosa completamente sin sentido para ejecutar, sería estilísticamente mejor escribirlo como x; return y;
x; return y;
, que es exactamente lo mismo. No sería tan confuso de esa manera.
Por un lado, podría ser un error honesto por parte del escritor.
Por otro lado, el escritor podría estar explicando el código correcto sintácticamente correcto, en lugar de las advertencias del compilador.
De cualquier manera, la única manera de devolver múltiples resultados sería definir una clase y usar su instancia, o tal vez una matriz o colección.
struct Point {
int x, y;
Point(int x_) : x(x_), y(0) {}
Point(const Point& p) : x(p.x), y(p.y) {}
Point operator, (int y_) const { Point p=*this; p.y = y_; return p; }
};
Point get_the_point () {
int x = 0;
int y = 20;
return (Point)x, y;
}
:pag