c++ - not - ¿Es seguro#define NULL nullptr?
nullptr was not declared in this scope (6)
He visto a continuación la macro en el archivo de encabezado superior:
No debería haberlo visto, la biblioteca estándar lo define en <cstddef>
(y <stddef.h>
). Y, IIRC, según el estándar, la redefinición de los nombres definidos por los archivos de encabezado estándar da como resultado un comportamiento indefinido. Entonces, desde un punto de vista puramente estándar, no deberías hacer eso.
He visto a gente hacer lo siguiente, por el motivo que sea su mente rota:
struct X{
virtual void f() = NULL;
}
(Como en [incorrectamente]: "establecer el puntero de la tabla virtual a NULL
")
Esto solo es válido si NULL
se define como 0
, porque = 0
es el token válido para funciones virtuales puras ( §9.2 [class.mem]
).
Dicho esto, si NULL
se usó correctamente como una constante de puntero nulo, entonces nada debería romperse.
Sin embargo, tenga en cuenta que, incluso si se usa aparentemente correctamente, esto cambiará:
void f(int){}
void f(char*){}
f(0); // calls f(int)
f(nullptr); // calls f(char*)
Sin embargo, si ese fuera el caso, era casi seguro que se rompió de todos modos.
He visto a continuación la macro en muchos archivos de encabezado superiores:
#define NULL 0 // C++03
En todo el código, NULL
y 0
se usan indistintamente. Si lo cambio a.
#define NULL nullptr // C++11
¿Causará algún efecto secundario malo? Puedo pensar en el único (bueno) efecto secundario ya que el siguiente uso se volverá mal formado;
int i = NULL;
Mucho mejor es buscar y reemplazar NULL
con nullptr
todo el código.
Puede ser sintácticamente seguro, pero ¿dónde colocarías el #define
? Crea problemas de organización de código.
No deberías definirlo en absoluto, a menos que estés escribiendo tu propia versión de <cstddef>
; ciertamente no debería estar en "muchos archivos de encabezado superiores".
Si está implementando su propia biblioteca estándar, entonces el único requisito es
18.2 / 3 La macro NULL es una constante de puntero nulo C ++ definida por la implementación
entonces 0
o nullptr
es aceptable, y nullptr
es mejor (si tu compilador lo admite) por la razón que das.
No. No puedes (re) definir macros estándar. Y si ves
#define NULL 0
en la parte superior de cualquier archivo que no sea un encabezado estándar (e incluso allí, debe incluir resguardos, y generalmente en guardias adicionales también), entonces ese archivo está roto. Eliminarlo
Tenga en cuenta que los buenos compiladores típicamente definirán NULL
con algo como:
#define NULL __builtin_null
, para acceder a un compilador incorporado que activará una advertencia si se usa en un contexto sin puntero.
Si bien podría romperse hacia atrás, la compatibilidad con las cosas más antiguas que estaba mal escrita (o eso, o demasiado inteligente ...) , para su código más nuevo, esto no es un problema. Deberías usar nullptr
, y no NULL
, donde te refieres a nullptr
. Además, debes usar 0
donde quieres decir cero.
Tal vez no
Si tiene un formato particular de comportamiento de sobrecarga:
void foo(int);
void foo(char*);
Entonces el comportamiento del código:
foo(NULL);
cambiará dependiendo de si NULL se cambia a nullptr o no.
Por supuesto, hay otra pregunta sobre si es seguro escribir el código que está presente en esta respuesta ...