2009-03-27 4 views
93
int fn(); 

void whatever() 
{ 
    (void) fn(); 
} 

¿Hay alguna razón para convertir un valor de retorno no utilizado en vacío, o estoy en lo cierto al pensar que es una completa pérdida de tiempo?¿Por qué arrojar los valores de devolución no utilizados a vacío?

seguimiento:

Bueno, eso parece bastante completa. Supongo que es mejor que comentar un valor de retorno no utilizado ya que el código de auto documentación es mejor que los comentarios. Personalmente, desactivaré estas advertencias ya que es un ruido innecesario.

voy a comer mis palabras, si un error se escapa a causa de ella ...

Respuesta

65

David's answer prácticamente cubre la motivación para esto, para mostrar explícitamente a otros "desarrolladores" que usted sabe que esta función devuelve pero que está ignorándolo explícitamente.

Esta es una forma de garantizar que siempre que sea necesario se manejen los códigos de error.

Creo que para C++ este es probablemente el único lugar en el que prefiero usar moldes de estilo C también, ya que usar la notación completa de cast estático simplemente parece exagerado aquí. Por último, si se está revisando un estándar de codificación o escribir uno, entonces también es una buena idea explícita estado que exige a los operadores sobrecargados (que no utilizan la notación llamada de función) debería estar exento de esto también:

class A {}; 
A operator+(A const &, A const &); 

int main() { 
    A a; 
    a + a;     // Not a problem 
    (void)operator+(a,a); // Using function call notation - so add the cast. 
+0

este es el único lugar en el que prefiero el estilo C también. Aunque en mi estándar de codificación, agregaría (vacío) a "a + a". también (correctamente incluido, por supuesto: p) –

+5

Algo fuera de tema, pero ¿por qué harías "a + a"? así sin usar el valor de retorno? Eso realmente me parece un abuso de los efectos secundarios, y ofusca la intención del código. –

+1

Bueno, el que usará todos los días será 'a = a'. Esto devuelve el objeto asignado (¡para todas las clases que se comportan bien eso! :)). Otro ejemplo es: os << "Hello World" << std :: endl. Cada uno de ellos devuelve el objeto "os". –

35

En el trabajo usamos que reconocer que la función tiene un valor de retorno, pero el desarrollador ha afirmado que es seguro ignorarla . Dado que la cuestión etiquetado como C++ debería utilizar static_cast:

static_cast<void>(fn()); 

Por lo que el compilador va echando el valor de retorno de anular tiene poco significado.

+0

¿Suprime la advertencia sobre los valores de devolución no utilizados? –

+0

¿Hay tal advertencia? –

+0

No, no es así. @Mykola: con GCC4 puede adjuntar un atributo que dice que no se debe ignorar el valor de retorno, lo que activará una advertencia. –

2

Cast to void no tiene costo. Es solo información para el compilador cómo tratarlo.

+1

Es "sin costo" si el tiempo para escribirlo y la lectura del tiempo posterior, entendiendo (y luego ignorando) el código es gratuito. IMO, escribiendo '(void)' me cuesta tiempo y energía y me hace preguntarme si el autor sabía cómo funcionan las expresiones. – wallyk

28

El La verdadera razón para hacer esto data de una herramienta utilizada en el código C, llamada lint.

Analiza el código buscando posibles problemas y emitiendo advertencias y sugerencias. Si una función devuelve un valor que luego no se verificó, lint advertiría en caso de que fuera accidental. Para silenciar lint en esta advertencia, realice la llamada al (void).

+1

Puede haber comenzado de esta manera, pero la mayoría de las herramientas ahora tienen otros mecanismos para suprimir advertencias como esta. Además, independientemente de por qué comenzó esto, dentro del dominio del código crítico de seguridad en particular, esta se ha convertido en la forma habitual de "documentar" las intenciones del desarrollador. –

+3

GCC da una advertencia para esto con -Wall. – greyfade

5

Para la funcionalidad de su programa de conversión a vacío no tiene sentido. También argumentaría que no debes usarlo para señalar algo a la persona que está leyendo el código, como se sugiere en la respuesta de David. Si desea comunicar algo acerca de sus intenciones, es mejor usar un comentario. Agregar un molde como este solo se verá extraño y hará preguntas sobre la posible razón. Solo mi opinión ...

+1

Este es un patrón conocido para indicar explícitamente a otros que no le importa el valor de retorno, que no se olvidó de manejarlo. – Spidey

+0

'Para la funcionalidad de su conversión de programa a vacío no tiene sentido' Para auto-documentación y el número de advertencias al compilar, _realmente_ no lo es. 'no deberías usarlo para señalar algo a la persona que está leyendo el código [...] es mejor usar un comentario.'El mejor comentario es _no comment_, cuando el código se explica a sí mismo. Y, de nuevo, mantiene un compilador de advertencia válido feliz en el proceso. –

+0

'Agregar un modelo como este solo se verá extraño y suscitará dudas sobre el posible motivo'. Descubrí uno de estos, y es por eso que estoy leyendo esto. Parecía un misterioso abuso de stack para mi cerebro no entrenado. – mynameisnafe

19

Casting a void se utiliza para suprimir las advertencias del compilador de las variables no utilizadas y los valores o expresiones de retorno no guardados.

The Standard (2003) dice en §5.2.9/4 dice,

Cualquier expresión puede ser explícitamente convertir al tipo “vacío cv.” El valor de la expresión es descartados.

para que pueda escribir:

//suppressing unused variable warnings 
static_cast<void>(unusedVar); 
static_cast<const void>(unusedVar); 
static_cast<volatile void>(unusedVar); 

//suppressing return value warnings 
static_cast<void>(fn()); 
static_cast<const void>(fn()); 
static_cast<volatile void>(fn()); 

//suppressing unsaved expressions 
static_cast<void>(a + b * 10); 
static_cast<const void>(x &&y || z); 
static_cast<volatile void>(m | n + fn()); 

Todas las formas son válidas. Normalmente lo hago más corto como:

//suppressing expressions 
(void)(unusedVar); 
(void)(fn()); 
(void)(x &&y || z); 

También está bien.

+0

Excepto que no siempre apaga las advertencias del compilador. gcc no parece responder a la conversión al void – Matt

+0

@Matt: ¿Qué versión de GCC estás usando? Puedes publicar tu código en ideone.com o stacked-crooked.com (este último es mejor). – Nawaz

+1

¿La fraseología estándar "descartada" implica que la advertencia no debe ser levantada por linters? –

2

En C, está perfectamente bien para lanzar al vacío. Prácticamente cualquiera entenderá la intención de la declaración.

En C++, tiene otras herramientas a su disposición. Desde moldes C están generalmente mal visto, y puesto que la conversión explícita de anular probable que sorprender a sus compañeros de trabajo (que sorprende a la mía), tengo esta plantilla de función en algún lugar

template <typename T> 
void use_expression(const T&) {} 

y utilizo

... 
use_expression(foo()); 

donde Escribiría (void)foo() en C.

+3

O simplemente "#define IGNORE_RESULT (fn) if (fn)". Funciona en C & C++ y el significado es muy claro. – Matt

+0

@Matt hay un problema con esa macro. ¿Qué tal 'if (x) IGNORE_RESULT (f()); else g(); '? El 'else' se adjunta a la declaración if incorrecta. –

+0

Colin, sí, eso es cierto. – Matt

1

También cuando verifique que su código cumpla con los estándares MISTA (u otros), las herramientas automáticas como LDRA no le permitirán llamar a una función que tenga un tipo de retorno sin tener que devolver un valor a menos tu e xplícitamente arrojar el valor devuelto a (void)

Cuestiones relacionadas