C++-NULL
NULL
在C/C++中,NULL是一个特殊的常量,可以被赋值(隐式转换)给任意指针类型!
在C中,NULL被定义成一个0值常量表达式或者该表达式被转型为
void*
,具体由实现决定
但语法上允许下面用法1
2int *pi1 = 0; // ok
int *pi2 = (void*)0; // ok在C++11之前,32位系统中,NULL被定义成0,64位被定义为0LL,这样在一定场景下会导致歧义!
C++11之后采用
nullptr
,不支持(void*)0
!1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int *pi1 = 0; // ok
int *pi2 = (void*)0; // error!
int *pi3 = 1; // error!
void DoSomething(int x);
void DoSomething(char* x);
DoSomething(NULL); // g++ 5.1.0: error: call of overloaded 'DoSomething(NULL)' is ambiguous
std::vector<int*> v(10);
// 模板根据NULL推断类型为long long int,而v对应的却是int*!
std::fill(v.begin(), v.end(), NULL); // error: error: invalid conversion from 'long long int' to 'int*'
void*
在C中,void*
从或者向其他类型指针隐式转换,但在C++中,不允许void*
隐式转换为其他类型指针!
1 | void *pv; |
1 | void *pv; |
为什么C++中采用#define NULL 0
,而不支持#define NULL ((void *)0)
呢?
在C中,假设开发人员知道他们所做的事,允许void*
隐式转换是为了方便程序开发。
而在C++中,为了保证类型安全,不建议使用C中的强制类型转换,以及void*
隐式转换(从语法层禁止!)
因为C++中,为了支持类,多态,类型之间任意转换,是很容易导致错误的!
假设允许void*
隐式转换:
1 | void *pa = new A; |
类似这样的代码不会发出任何警告,而这样的错误定位起来非常麻烦!
参考
- Why must I use a cast to convert from void*?
- http://stackoverflow.com/questions/7016861/why-are-null-pointers-defined-differently-in-c-and-c
- http://en.cppreference.com/w/c/language/conversion#Pointer_conversions
- http://en.cppreference.com/w/cpp/types/NULL
- http://softwareengineering.stackexchange.com/questions/275712/why-arent-void-s-implicitly-cast-in-c
- C++ 4.10.1