#define NULL nullptr是否安全?

iam*_*ind 42 c++ null nullptr c++11

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

#define NULL 0  // C++03
Run Code Online (Sandbox Code Playgroud)

在各地的代码,NULL并且0可以互换使用.如果我改成它.

#define NULL nullptr  // C++11
Run Code Online (Sandbox Code Playgroud)

它会导致任何不良副作用吗?我可以想到唯一的(好的)副作用,因为以下用法会变得格格不入;

int i = NULL;
Run Code Online (Sandbox Code Playgroud)

Xeo*_*Xeo 40

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

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


我见过人们做了以下事情,无论出于什么原因,他们心碎的想法:

struct X{
  virtual void f() = NULL;
}
Run Code Online (Sandbox Code Playgroud)

(如[错误]:"将虚拟表指针设置为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*)
Run Code Online (Sandbox Code Playgroud)

但是,如果情况确实如此,那几乎肯定会被打破.

  • 顺便说一句,如果你正在编写一个C++ 11实现,那么`#define NULL nullptr`是合法的,因为`nullptr`是一个空指针常量,而`NULL`可以是任何空指针常量.但是程序不允许自己决定应该是哪一个,这取决于实现. (12认同)
  • @Steve:`§9.2[class.mem]`:`pure-specifier:= 0`. (8认同)
  • `virtual void f()= 0L;`合法吗?因为`#define NULL 0L`肯定是一致的实现. (7认同)
  • @iammilind:你不应该,因为标准已经定义了`NULL`. (6认同)

spr*_*aff 14

更好的是搜索和替换NULLnullptr整个代码.

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

  • `g ++ -DNULL = nullptr ...`:) (10认同)
  • 我认为需要某些编译器标志的代码是不可移植的. (7认同)
  • 有一个*可选的*`-Dmode`开关是合理的,假设代码仍可以在没有它的情况下编译.此外,并非每个项目都需要跨平台,但在这种情况下,您不需要`-DWindows`或`-DnythingElse`,因为它是内置的. (2认同)

Jam*_*nze 7

不.您不允许(重新)定义标准宏.如果你看到了

#define NULL 0
Run Code Online (Sandbox Code Playgroud)

在除标准标题之外的任何文件的顶部(甚至在那里,它应该在包括警卫中,并且通常在其他警卫中),然后该文件被破坏.去掉它.

请注意,好的编译器通常会定义NULL如下:

#define NULL __builtin_null
Run Code Online (Sandbox Code Playgroud)

,访问内置的编译器,如果在非指针上下文中使用它将触发警告.