是否安全#define NULL nullptr?

我在下面的macros中看到了许多最顶级的头文件:

#define NULL 0 // C++03 

在所有的代码中, NULL0可以互换使用。 如果我改变它。

 #define NULL nullptr // C++11 

会造成不良副作用吗? 我可以想到以下用法的唯一(好)副作用将会变形,

 int i = NULL; 

我在最顶层的头文件中看到了下面的macros:

您应该没有看到,标准库在<cstddef> (和<stddef.h> )中定义它。 而且,根据标准,IIRC重新定义由标准头文件定义的名称会导致未定义的行为。 所以从纯粹的观点来看,你不应该那样做。


我已经看到人们做了以下事情,无论出于何种原因他们的思想破碎:

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

(如在[不正确]中:“将虚拟表指针设置为NULL ”)

这只有在NULL定义为0时才有效,因为= 0是纯虚函数( §9.2 [class.mem] )的有效标记。

也就是说, 如果NULL正确地用作空指针常量,那么什么都不应该中断。

但是,要小心,即使看似正确使用,这也会改变:

 void f(int){} void f(char*){} f(0); // calls f(int) f(nullptr); // calls f(char*) 

但是,如果是这样的话,反正几乎肯定是坏的。

更好的是在整个代码中用nullptrsearch和replaceNULL

它可能在语法上是安全的,但是你会在哪里放置#define ? 它会产生代码组织问题。

不,你不能(重新)定义标准的macros。 如果你看到

 #define NULL 0 

在标准标题以外的任何文件的顶部(甚至在那里,它应该在包括守卫中,并且通常在附加的守卫中),那么该文件被破坏。 去掉它。

请注意,好的编译器通常会用类似下面的方式定义NULL

 #define NULL __builtin_null 

,要访问一个编译器内build函数,如果它在非指针上下文中使用,将会触发一个警告。

除非你编写自己的<cstddef>版本,否则你不应该定义它。 它当然不应该在“许多最顶级的头文件”中。

如果你正在实现你自己的标准库,那么唯一的要求是

18.2 / 3macrosNULL是一个实现定义的C ++空指针常量

所以无论是0还是nullptr都是可以接受的,而nullptr更好(如果你的编译器支持的话)。

也许不会

如果你有一个特定的重载行为格式:

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

那么代码的行为:

 foo(NULL); 

将根据NULL是否更改为nullptr而改变。

当然,还有另外一个问题,就是在这个答案中写出这样的代码是否安全?

虽然它可能会破坏旧版本的兼容性,但是对于较新的代码来说,这是一个没有问题的事情。 你应该使用nullptr ,而不是NULL ,你的意思是nullptr 。 此外,你应该使用0 ,你的意思是零。