Is it safe to #define NULL nullptr?



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

#define NULL 0  // C++03

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

#define NULL nullptr  // C++11

它会引起不良副作用吗?我能想到的唯一(好的)副作用是以下用法会变得不规范;

int i = NULL;

我在最上面的头文件中看到了下面的宏:

您不应该看到,标准库在<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*)

然而,如果真是这样的话,它几乎肯定会被打破。

更好的方法是在整个代码中搜索NULL并用nullptr替换。

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

否。不允许(重新)定义标准宏。如果你看到

#define NULL 0

在除标准标头之外的任何文件的顶部(甚至在那里,它应在包含防护装置中,通常在附加防护装置中好吧),那么那个文件就坏了。移除它。

注意,优秀的编译器通常会用一些东西来定义NULL类似:

#define NULL __builtin_null

,访问编译器内建,如果是在非指针上下文中使用。

您根本不应该定义它,除非您正在编写自己版本的<cstddef>;它当然不应该出现在"许多最顶端的头文件"中。

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

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

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

也许不是

如果你有一种特殊的过载行为格式:

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

然后代码的行为:

foo(NULL);

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

当然,还有另一个问题是,编写这个答案中的代码是否安全。。。

虽然它可能会破坏与写得不好的旧东西的向后兼容性(要么是这样,要么过于聪明…),但对于您的新代码来说,这不是问题。应该使用nullptr,而不是NULL,这里的意思是nullptr。此外,您应该使用0来表示零。

最新更新