2012-01-25 14 views
40

que he visto debajo de macro en muchos archivos de cabecera más altas:¿Es seguro #define NULL nullptr?

#define NULL 0 // C++03 

En todo el código, y NULL0 se utilizan 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; 

Respuesta

39

que he visto debajo de macro en el archivo de cabecera superior:

No deberías haber visto que, la biblioteca estándar 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.


gente que he visto hacer lo siguiente, por cualquier razón su mente roto pensamiento de:

struct X{ 
    virtual void f() = NULL; 
} 

(como en [mal]: "establecer el puntero de la tabla virtual para NULL")

Esto solo es válido si NULL se define como 0, porque = 0 es el token válido para funciones puramente virtuales (§9.2 [class.mem]).

Dicho esto, si NULL fue correctamente utilizarse como una constante puntero nulo, entonces nada debe romper.

Sin embargo, ten en cuenta que, aunque aparentemente se utiliza correctamente, esto va a cambiar:

void f(int){} 
void f(char*){} 

f(0); // calls f(int) 
f(nullptr); // calls f(char*) 

Sin embargo, si ese era siempre el caso, es casi seguro que fue roto de todos modos.

+0

'No deberías haber visto eso'. ¿Por qué te sientes así? Incluso he visto una macro extraña como, '#define NULL (void *) (0)' en un código de producción para DSP para WCDMA L1. – iammilind

+6

Es 'virtual void f() = 0L;' legal? Porque '#define NULL 0L' ciertamente es una implementación conforme. –

+6

@iammilind: No deberías, porque 'NULL' ya está definido por el estándar. – Xeo

14

mucho mejor es buscar y reemplazar NULL con nullptr en todo el código.

Puede ser sintácticamente seguro, pero ¿dónde pondría el #define? Crea problemas de organización de código.

+10

'g ++ = -DNULL nullptr ...' :) – Xeo

+7

considero código que requiere cierta las banderas del compilador no son portátiles. – spraff

+0

Bueno, supongo que ya no podemos -DWindows, ni nada de eso, y tenemos que volver a escribir todo nuestro código para transferirlo a otra plataforma ... –

2

Si bien puede romper la compatibilidad con versiones anteriores que fue mal escrita (o eso, o demasiado inteligente ...), para su código más reciente, esto no es un problema. Debe usar nullptr, y no NULL, donde quiere decir nullptr. Además, debe usar 0 donde quiere decir cero.

+3

Tenga en cuenta que las cosas antiguas bien escritas tampoco usarán 'nullptr', ya que solo se agregó al idioma hace unos meses. –

+1

@Mike: las cosas antiguas bien escritas pueden tener algo como '#define NULLPTR NULL', sin embargo, que se puede cambiar a' #define NULLPTR nullptr' al compilar como C++ 11. Y luego todas las instancias de 'NULLPTR' en el código eliminado una vez que esté seguro de que nunca más tendrá que compilarlo como C++ 03. –

+1

@SteveJessop ¿En serio? Quiero decir, tal vez ahora que sabemos sobre nullptr que la macro NULLPTR tendría sentido, pero el código anterior (* before * nullptr se agregó al estándar) teniendo eso parece ... improbable. – luiscubal

4

No debe definirlo en absoluto, a menos que esté escribiendo su propia versión de <cstddef>; ciertamente no debería estar en "muchos archivos de encabezado superiores".

Si va a implementar su propia biblioteca estándar, entonces el único requisito es

18,2/3 El NULL macro es un C definido por la implementación ++ constante puntero nulo

así que o 0 o nullptr es aceptable, y nullptr es mejor (si su compilador lo admite) por el motivo que usted brinda.

7

No. No tiene permiso para (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 estar en incluir guardias, y típicamente en guardias adicionales como así), entonces ese archivo se rompe . Eliminarlo

Nota que los buenos compiladores suelen definir NULL con algo como:

#define NULL __builtin_null 

, para acceder a una orden interna del compilador, lo que disparará una advertencia si es utilizado en un contexto no-puntero.

+0

Tal vez esa es la razón por la que fue redefinido: forma perezosa de espantar las advertencias ... –

4

Tal vez no

Si usted tiene un formato particular de comportamiento sobrecarga:

void foo(int); 
void foo(char*); 

A continuación, el comportamiento del código:

foo(NULL); 

cambiará dependiendo de si NULL es cambiado a nullptr o no.

Por supuesto, hay otra pregunta en cuanto a si es seguro para escribir dicho código como está presente en esta respuesta ...