2011-10-17 10 views
5

Supongamos que tengo una función que arroja un resultado importante y varios resultados sin importancia. Declaré que para que los resultados se devuelven sin importancia por referencia:Ignorar un resultado de devolución por referencia de una función

int CalculateStuff(int param1, int param2, int& result1, int& result2); 

me gustaría llamar a esta función para calcular algunas cosas, pero en el sitio llamado quiero ignorar los resultados sin importancia. Podría hacerlo de la siguiente manera:

... 
int dummy1, dummy2; 
int result = CalculateStuff(100, 42, dummy1, dummy2); 
... // do something with the result 

me gustaría considerar otra forma de hacer lo mismo sin la declaración de variables ficticias:

int result = CalculateStuff(100, 42, *new int, *new int); 

Esto tiene una pérdida de memoria (inaceptable), pero tiene una ventaja de mostrar mi intención (ignorando los resultados) más claramente que los nombres "ficticios".

Entonces, ¿qué pasaría si yo escribí como sigue:

int result = CalculateStuff(100, 42, auto_ptr(new int).get(), auto_ptr(new int).get()); 

¿Es legal? ¿Los enteros temporales todavía existirán cuando se ejecute el código de la función? ¿Debo usar unique_ptr en lugar de auto_ptr?

(Por favor, no sugieren refactorización mi código, yo probablemente lo hará - pero primero quiero entender cómo funciona esto)

+1

Agregado como un comentario, ya que en realidad no responde su pregunta, pero generalmente declaro una llamada temporal _ y la paso si aparece. "CalculateStuff (100, 42, _, _); parece razonablemente claro. – jcoder

Respuesta

4

es legal; auto_ptr objetos permanecerán vivos hasta el final de la expresión (es decir, llamada de función). Pero es feo como el infierno.

Sólo sobrecargue su función:

int CalculateStuff(int param1, int param2, int& result1, int& result2); 
int CalculateStuff(int param1, int param2) { 
    int r1=0, r2=0; 
    return CalculateStuff(param1, param2, r1, r2); 
} 
+1

Eso todavía plantea la * misma * pregunta, ¿cómo vas a implementar la segunda sobrecarga? ¿Vas a usar variables ficticias, o' * new int? o 'auto_ptr', o qué, para que pueda llamar a la primera sobrecarga del segundo? – Nawaz

+0

@Nawaz, por ejemplo, creando dos variables temporales, o llamando a una tercera implementación (por ejemplo, la que tiene los punteros que sugirió). – hamstergene

+0

Pero esa es exactamente la pregunta. – Nawaz

3

Un enfoque que se recomienda si usted tiene el control sobre la función sería la siguiente: devolver un std::tuple (o boost::tuple) con todos los resultados o escribir una sobrecarga que no necesita el extra variables.

3

Este es mi consejo: si tiene que solicitar SO para averiguar la exactitud del código y su semántica, entonces el código falla al expresar claramente su intención.

Creo que la primera versión (con dummy1 y dummy2) es la más transparente, y obviamente es correcta.

Si usted se encuentra en varias ocasiones llamando a la función y no querer los resultados opcionales, que podría proporcionar una sobrecarga:

int CalculateStuff(int param1, int param2, int& result1, int& result2) {} 

int CalculateStuff(int param1, int param2) { 
    int unwanted1, unwanted2; 
    return CalculateStuff(param1, param2, unwanted1, unwanted2); 
} 
4

Según Bjarne Stroustrup, si algunos parámetros son opcionales, es un caso ideal para hacer a un tipo de puntero, por lo que puede pasar NULL cuando no es necesario pasar argumentos para ellos:

int CalculateStuff(int param1, int param2, int * result1, int * result2); 

y uso:

int result = CalculateStuff(100, 42, NULL, NULL); 

Todas las otras alternativas no serían tan buenas como esta, o al menos no mejor que.

Por supuesto, la implementación de CalculateStuff tiene que verificar los parámetros si son NULL o no.

3

Puede hacer una clase que proporcione una conversión implícita (o explícita) a int&.

struct ignored 
{ 
    int n; 
    operator int&() { return n; } 
}; 

n = CalculateStuff(a, b, ignored(), ignored()); 

Puede seguir haciendo de esta una plantilla y agregar sobrecargas const.

+0

no será el tipo de ignorado const y le dará problemas? –

+0

@WinstonEwert: ¿Por qué? Un temporal no se puede enlazar a una referencia no directa directamente. Sin embargo, uno puede llamar a métodos no const de un objeto temporal. De eso se está aprovechando. – UncleBens

2

Es legal, pero no se garantiza que no se pierda la memoria, consulte la pregunta 3 here por ejemplo.

La forma correcta e idiomático de la aplicación de salida opcional es pasar un puntero , pasando NULL cuando no se desea que los resultados, y las pruebas de NULL en la función antes de escribir a través del puntero.

Cuestiones relacionadas