我在许多最顶层的头文件中看到了下面的宏:
#define NULL 0 // C++03
在所有的代码中,NULL
都0
可以互换使用。如果我将其更改为。
#define NULL nullptr // C++11
会不会有什么不好的副作用?我能想到的唯一(好的)副作用是以下用法会变得不正确;
int i = NULL;
我在最顶层的头文件中看到了下面的宏:
您不应该看到,标准库在<cstddef>
(and <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++ 空指针常量
所以要么0
ornullptr
是可以接受的,并且nullptr
更好(如果你的编译器支持它)你给出的原因。
也许不吧
如果您有特定格式的重载行为:
void foo(int);
void foo(char*);
然后代码的行为:
foo(NULL);
将根据 NULL 是否更改为 nullptr 而更改。
当然,还有另一个问题是编写此答案中存在的代码是否安全……
虽然它可能会破坏与写得不好(或者过于聪明......)的旧东西的向后兼容性,但对于您的新代码来说,这不是问题。你应该使用nullptr
,而不是NULL
你的意思nullptr
。此外,您应该使用0
您的意思为零的地方。