c++ visual-studio-2005 warnings

¿Cómo lidiar con la advertencia "inicializada pero no referenciada" de C++ para la destrucción de los ayudantes del alcance?



visual-studio-2005 warnings (12)

El problema principal aquí parece ser que el compilador no comprende a qué se dirige ... lo que parece ser usar la semántica de alcance en C ++ para obtener un código llamado cuando una variable es desasignada incluso cuando no se usa . ¿Derecha? Ese mecanismo en sí me parece algo dudoso ... un compilador debería tener el derecho de eliminar las variables no utilizadas, pero la semántica de construcción de C ++ realmente arruina estas cosas. ¿No hay otra manera de hacer esto que sea menos prestidigitación?

En Visual Studio, a menudo uso objetos solo para propósitos de RAII. Por ejemplo:

ScopeGuard close_guard = MakeGuard( &close_file, file );

El propósito de close_guard es asegurarse de que el archivo estará cerrado al salir de la función, no se usa en ningún otro lado. Sin embargo, Visual Studio me advierte que una " variable local se inicializa pero no se hace referencia ". Quiero desactivar esta advertencia para este caso específico.

¿Cómo lidias con este tipo de situación? Visual Studio cree que este objeto es inútil, pero esto es incorrecto ya que tiene un destructor no trivial.

No me gustaría usar una directiva de advertencia de #pragma para esto ya que desactivaría esta advertencia incluso por razones legítimas.


En algunos de los archivos de encabezado de VC ++, MS define una macro:

#define UNUSED(x) x

usado como:

ScopeGuard close_guard = MakeGuard( &close_file, file ); UNUSED(close_guard);

Lo cual silencia la advertencia y la documenta.


Intente agregar ''volátil'' a la declaración de ScopeGuard.


Podría crear explícitamente el objeto ScopeGuardImpl1, siempre que no haya tantos parámetros en los casos que esté utilizando que el resultado sea ilegible. De esta forma, evitaría la referencia inicializada con temporal que la advertencia VS aparentemente no puede comprender. El costo es tener que deletrear las cosas a mano, en lugar de hacer que la plantilla de MakeGuard sea mágica.


Puede delimitar la advertencia de #pragma alrededor de esa línea de código utilizando solo

#pragma warning(push) #pragma warning(disable:XXXX) your code here; #pragma warning(pop)

o

#pragma warning(disable:XXXX) your code here; #pragma warning(default:XXXX)

También puede usar UNREFERENCED_PARAMETER(close_guard); después de la línea de código de arriba.


Si su objeto tiene un destructor no trivial, Visual Studio no debería darle esa advertencia. El siguiente código no genera advertencias en VS2005 con advertencias subidas (/ W4):

class Test { public: ~Test(void) { printf("destructor/n"); } }; Test foo(void) { return Test(); } int main(void) { Test t = foo(); printf("moo/n"); return 0; }

Comentando el destructor da una advertencia; el código tal cual no.


Supongo que en la práctica, me gustaría ir con el #pragma disable ... o ''UNUSED''. Sin embargo, como regla principal, el código debe mantenerse limpio de advertencias, incluso a costa de algún volumen adicional. Debe compilarse en múltiples compiladores diferentes en diferentes plataformas y sistemas operativos sin advertencias. Si no es así, el código ha sido corregido para que así sea. Mantener el código que genera advertencias en gcc -Wall level no es una buena idea.

Las advertencias del compilador son su amigo, y deben ser atendidas como una cuestión o principio. Incluso cuando eso significa que las cosas tienen que implementarse de una manera un poco más voluminosa y más detallada. Se paga a la larga a medida que el código se transporta, mantiene y se mantiene vivo para siempre ...


Usamos:

static_cast<void>(close_guard);

para variables de las que el compilador se queja.


Utilizaría macro todo el camino en este caso:

#define SCOPE_GUARD(guard, fn, param) / ScopeGuard guard = MakeGuard(fn, param); / static_cast<void>(guard)

ahora tu código es bueno y corto:

SCOPE_GUARD(g1, &file_close, file1); SCOPE_GUARD(g2, &file_close, file2);

Una ventaja de este enfoque es que más adelante puede agregar __LINE__ , __func__ para registrar las acciones de guarda más adelante si es necesario.


Utilizo la publicación de smink anterior y solo tengo que agregar que incluyo un comentario al lado del #define diciendo // usado para suprimir la advertencia [número de advertencia] en el estudio visual


Bueno, en este caso ScopeGuard es en realidad un typedef a un tipo de referencia. Esto no funcionaría por desgracia.

¿No significa eso que ScopeGuard no funciona, porque en ese caso el destructor no se llamará?


Método 1: utilice la directiva de #pragma warning .

#pragma warning permite la modificación selectiva del comportamiento de los mensajes de advertencia del compilador.

#pragma warning( push ) #pragma warning( disable : 4705 ) // replace 4705 with warning number ScopeGuard close_guard = MakeGuard( &close_file, file ); #pragma warning( pop )

Este código guarda el estado de advertencia actual, luego deshabilita la advertencia de un código de advertencia específico y luego restaura el último estado de advertencia guardado.

Método 2: use una solución como la siguiente. Visual Studio estará feliz y tú también. Esta solución alternativa se utiliza en muchas muestras de Microsoft y también en otros proyectos.

ScopeGuard close_guard = MakeGuard( &close_file, file ); close_guard;

O puede crear un #define para solucionar la advertencia.

#define UNUSED_VAR(VAR) VAR ... ScopeGuard close_guard = MakeGuard( &close_file, file ); UNUSED_VAR(close_guard);

Algunos usuarios declararon que el código presentado no funcionará porque ScopeGuard es un typedef. Esta suposición es incorrecta.

http://www.ddj.com/cpp/184403758

De acuerdo con el Estándar C ++, una referencia inicializada con un valor temporal hace que ese valor temporal viva durante el tiempo de vida de la referencia misma.