2012-02-04 26 views
1

众所周知,没有空引用。
所以我尝试编译这行代码可以吗?

int main{ 
    int &surprise_reference=*(int*)0; 
    return 0;} 

令我吃惊的此代码的工作没有一个单一的警告。
然后我我的代码更改为

int main() { 
int&suprise_reference=*(int*)0; 
if(&suprise_reference==0) 
std::cout<<"you don't know references"; 
      return 0; 
} 

输出程序的你不知道引用
这是否意味着解引用空指针也会导致空引用?
请帮忙..

回答

3

您的实验显示它恰好适用于您的特定计算机。这并不意味着它是“好的”。

特别是,这条线:

int &surprise_reference=*(int*)0; 

无效C++代码,因为(完全是你所述)的参考是不允许指向一个NULL指针。做一些C++标准所不允许的事情的结果是未定义的行为。在这种特殊情况下,在您的特定计算机上,未定义的行为恰好是非常温和的,但这并不能使其可预测或始终正常。

查看https://isocpp.org/wiki/faq/references#refs-vs-ptrs了解更多详情。他们特别指出的一件事是,因为编译器知道创建一个空引用是非法的,所以可能会认为你没有做到这一点 - 例如,如果你有一个函数需要p作为参数,和你写

int &q = *(int*)p; 
if (p == NULL) 
    ... 

它可以从基准创造,p是已知的非NULL总结,并优化掉的检查。然后,如果你传入一个NULL指针p,事情可能会严重错误。

(诸如此类的假设和优化,顺便说一下,是很多从不确定代码不好的事情是如何发生的。)

+2

澄清:在“知道这是非法的”,在“本”指的是创建'NULL'引用的一般行为,而不是这段特定的代码。大多数现代编译器不检查是否将常量零转换为指针类型,并在发生这种情况时将创建的指针标记为“NULL”。因此,'(int *)0'创建一个通用的'int *',它被视为与其他任何'int'指针一样。 – Borealid 2012-02-04 06:18:31

+0

@Borealid:谢谢你的澄清!我在答案中做了相关的编辑。 – 2012-02-04 19:11:49

1

修复代码中的错误和奥秘将消失。是的,有错误的代码会做一些奇怪的事情。这并不令人感到意外,也没有什么深远的意义。

4

可以有一个参考,最终指向NULL。这是未定义行为逃避编译器分析的结果。一个简单的例子就是一个填充整个堆的程序,包括存储引用的地址和零。显然,如果你这样做了,那么引用将指向内存地址零。

C++标准禁止创建到NULL类型一引用,而不是参考永远成为NULL。所有类型的安全性只有在编译器能够推断所讨论的类型的情况下才被执行 - 使用硬C类型的转换会严重阻碍该能力。