tem*_*def 102
回到C++ 03中,空指针由ISO规范(§4.10/ 1)定义为
空指针常量是整数类型的整数常量表达式(5.19)rvalue,其值为零.
这就是为什么在C++中你可以编写
int* ptr = 0;
Run Code Online (Sandbox Code Playgroud)
在C中,此规则类似,但有点不同(§6.3.2.3/ 3):
值为0的整型常量表达式或此类表达式转换为类型
void *
,称为空指针常量.55)如果将空指针常量转换为指针类型,则生成的指针(称为空指针)保证为比较不等于指向任何对象或函数的指针.
因此,两者
int* ptr = 0;
Run Code Online (Sandbox Code Playgroud)
和
int* ptr = (void *)0
Run Code Online (Sandbox Code Playgroud)
是合法的.但是,我的猜测是,void*
演员阵容就在这里,所以语句就像
int x = NULL;
Run Code Online (Sandbox Code Playgroud)
在大多数系统上生成编译器警告.在C++中,这不合法,因为如果没有强制转换,您无法隐式地将a隐式转换void*
为另一种指针类型.例如,这是非法的:
int* ptr = (void*)0; // Legal C, illegal C++
Run Code Online (Sandbox Code Playgroud)
但是,这会导致问题,因为代码
int x = NULL;
Run Code Online (Sandbox Code Playgroud)
是合法的C++.由于这个和随之而来的混乱(以及后面所示的另一种情况),从C++ 11开始,有一个nullptr
表示空指针的关键字:
int* ptr = nullptr;
Run Code Online (Sandbox Code Playgroud)
这没有任何上述问题.
nullptr
超过0 的另一个优点是它在C++类型系统中表现更好.例如,假设我有这两个函数:
void DoSomething(int x);
void DoSomething(char* x);
Run Code Online (Sandbox Code Playgroud)
如果我打电话
DoSomething(NULL);
Run Code Online (Sandbox Code Playgroud)
它相当于
DoSomething(0);
Run Code Online (Sandbox Code Playgroud)
它调用DoSomething(int)
而不是预期的DoSomething(char*)
.但是,nullptr
我可以写
DoSomething(nullptr);
Run Code Online (Sandbox Code Playgroud)
它将DoSomething(char*)
按预期调用该函数.
类似地,假设我有一个vector<Object*>
并且想要将每个元素设置为空指针.使用该std::fill
算法,我可能会尝试写作
std::fill(v.begin(), v.end(), NULL);
Run Code Online (Sandbox Code Playgroud)
但是,这不会编译,因为模板系统将其NULL
视为int
而不是指针.要解决这个问题,我必须写
std::fill(v.begin(), v.end(), (Object*)NULL);
Run Code Online (Sandbox Code Playgroud)
这很丑陋,有点违背了模板系统的目的.要解决这个问题,我可以使用nullptr
:
std::fill(v.begin(), v.end(), nullptr);
Run Code Online (Sandbox Code Playgroud)
并且因为nullptr
已知有一个类型对应于空指针(具体而言std::nullptr_t
),这将正确编译.
希望这可以帮助!
Kei*_*son 17
在C中,NULL
扩展为实现定义的"空指针常量".空指针常量是值为0的整型常量表达式,或者是这样的表达式void*
.所以C实现可以定义NULL
为as 0
或as ((void*)0)
.
在C++中,空指针常量的规则是不同的.特别是,((void*)0)
不是C++空指针常量,因此C++实现无法定义NULL
这种方式.
归档时间: |
|
查看次数: |
58410 次 |
最近记录: |