guia - Parámetro no utilizado en c++ 11
qgis manual (12)
En c ++ 03 y anteriores para deshabilitar la advertencia del compilador sobre el parámetro no utilizado usualmente uso dicho código:
#define UNUSED(expr) do { (void)(expr); } while (0)
Por ejemplo
int main(int argc, char *argv[])
{
UNUSED(argc);
UNUSED(argv);
return 0;
}
Pero las macros no son las mejores prácticas para c ++, entonces. ¿Alguna solución mejor aparece con el estándar c ++ 11? Quiero decir, ¿puedo deshacerme de las macros?
¡Gracias por todo!
¿Qué tienes en contra de la forma antigua y estándar?
void f(int a, int b)
{
(void)a;
(void)b;
return;
}
El encabezado de Boost <boost/core/ignore_unused.hpp>
(Boost> = 1.56) define, para este propósito, la plantilla de la función boost::ignore_unused()
.
int fun(int foo, int bar)
{
boost::ignore_unused(bar);
#ifdef ENABLE_DEBUG_OUTPUT
if (foo < bar)
std::cerr << "warning! foo < bar";
#endif
return foo + 2;
}
PS C ++ 17 parece estar obteniendo un atributo [[maybe_unused]]
para proporcionar una forma estándar de declarar una variable no utilizada.
Existe la <tuple>
en C ++ 11 , que incluye el objeto estándar listo para usar std::ignore
, que nos permite escribir (muy probablemente sin imponer gastos generales de tiempo de ejecución):
void f(int x)
{
std::ignore = x;
}
He usado una función con un cuerpo vacío para ese propósito:
template <typename T>
void ignore(T &&)
{ }
void f(int a, int b)
{
ignore(a);
ignore(b);
return;
}
Espero que cualquier compilador serio optimice la función llamada y silencia las advertencias para mí.
Las macros pueden no ser ideales, pero hacen un buen trabajo para este propósito en particular. Yo diría que se adhieren a usar la macro.
Me gusta usar macros para esto, porque te permite controlar mejor cuando tienes diferentes compilaciones de depuración (por ejemplo, si quieres construir con aserciones habilitadas):
#if defined(ENABLE_ASSERTS)
#define MY_ASSERT(x) assert(x)
#else
#define MY_ASSERT(x)
#end
#define MY_UNUSED(x)
#if defined(ENABLE_ASSERTS)
#define MY_USED_FOR_ASSERTS(x) x
#else
#define MY_USED_FOR_ASSERTS(x) MY_UNUSED(x)
#end
y luego usarlo como:
int myFunc(int myInt, float MY_USED_FOR_ASSERTS(myFloat), char MY_UNUSED(myChar))
{
MY_ASSERT(myChar < 12.0f);
return myInt;
}
No hay nada nuevo disponible.
Lo que funciona mejor para mí es comentar el nombre del parámetro en la implementación. De esta forma, se deshace de la advertencia, pero aún retiene alguna noción de cuál es el parámetro (ya que el nombre está disponible).
Su macro (y cualquier otro enfoque de conversión al vacío) tiene la desventaja de que puede usar el parámetro después de usar la macro. Esto puede hacer que el código sea más difícil de mantener.
Para "desactivar" esta advertencia, lo mejor es evitar escribir el argumento, solo escriba el tipo.
void function( int, int )
{
}
o si lo prefiere, coméntelo:
void function( int /*a*/, int /*b*/ )
{
}
Puede mezclar argumentos con nombre y sin nombre:
void function( int a, int /*b*/ )
{
}
Puedes omitir los nombres de los parámetros:
int main(int, char *[])
{
return 0;
}
Y en el caso de main, incluso puedes omitir los parámetros por completo:
int main()
{
// no return implies return 0;
}
Consulte "§ 3.6 Inicio y terminación" en el estándar C ++ 11.
Tengo mi propia implementación para segmentos críticos de código de tiempo. He estado investigando durante un tiempo un código de tiempo crítico para reducir la velocidad y he descubierto que esta implementación consume aproximadamente el 2% del código de tiempo crítico que he estado optimizando:
#define UTILITY_UNUSED(exp) (void)(exp)
#define UTILITY_UNUSED2(e0, e1) UTILITY_UNUSED(e0); UTILITY_UNUSED(e1)
#define ASSERT_EQ(v1, v2) { UTILITY_UNUSED2(v1, v2); } (void)0
El código de tiempo crítico ha utilizado las definiciones ASSERT*
para fines de depuración, pero en el lanzamiento se ha cortado claramente, pero ... Parece que esto produce un código más rápido en Visual Studio 2015 Update 3
:
#define UTILITY_UNUSED(exp) (void)(false ? (false ? ((void)(exp)) : (void)0) : (void)0)
#define UTILITY_UNUSED2(e0, e1) (void)(false ? (false ? ((void)(e0), (void)(e1)) : (void)0) : (void)0)
¿El motivo es doble false ?
expresión. De alguna manera produce un código un poco más rápido en lanzamiento con optimización máxima.
No sé por qué esto es más rápido (parece un error en la optimización del compilador), pero al menos es una mejor solución para ese caso de código.
Nota : Lo más importante aquí es que un código de tiempo crítico reduce la velocidad sin las aserciones anteriores o las macros inutilizadas en la versión. En otras palabras, ¿el doble false ?
expresión sorprendentemente ayuda a optimizar un código.
windows.h define UNREFERENCED_PARAMETER :
#define UNREFERENCED_PARAMETER(P) {(P) = (P);}
Entonces podrías hacerlo así:
#include <windows.h>
#include <stdio.h>
int main(int argc, char **argv) {
UNREFERENCED_PARAMETER(argc);
puts(argv[1]);
return 0;
}
O fuera de Windows:
#include <stdio.h>
#define UNREFERENCED_PARAMETER(P) {(P) = (P);}
int main(int argc, char **argv) {
UNREFERENCED_PARAMETER(argc);
puts(argv[1]);
return 0;
}
Nada equivalente, no.
Entonces estás atrapado con las mismas viejas opciones. ¿Estás feliz de omitir por completo los nombres en la lista de parámetros?
int main(int, char**)
En el caso específico de main
, por supuesto, simplemente podría omitir los parámetros:
int main()
También existen los típicos trucos específicos de implementación, como __attribute__((unused))
GCC __attribute__((unused))
.