2010-04-28 232 views
31

我想了解一下什么的C++标准说,关于这样的代码:C++标准:取消引用NULL指针以获取引用?

int* ptr = NULL; 
int& ref = *ptr; 
int* ptr2 = &ref; 

在实践中,结果是ptr2为NULL,但我不知道,这只是一个实现细节,或者这是明确定义在标准?
在不同的情况下,一个NULL指针的解引用应该导致崩溃,但是在这里,我将它解引用以获得由编译器实现的引用作为指针,所以实际上并没有实际的NULL解引用。

+5

http://stackoverflow.com/questions/2474018/when-does-invoking-a-member-function-on-a-null-instance-result-in-undefined-behav正在提供一个非常好的答案问题。 – pmr 2010-04-28 08:32:00

+0

链接副本:[将一个NULL指针取消引用到未使用的引用;这也是“未定义行为”?](http:// stackoverflow。com/q/40216965/514235) – iammilind 2016-10-24 11:22:03

回答

44

解引用NULL指针是未定义的行为。

事实上的标准调用这个确切情况的一份说明(8.3.2/4“参考”):

注:尤其是空引用不能在一个明确的程序存在,因为创建这种引用的唯一方法是将其绑定到通过取消引用空指针获得的“对象”,这会导致未定义的行为。


顺便说一句:在有一次我在一个明确定义的方式所知道的,一个空指针可以“引用”是作为操作的sizeof操作,因为操作数sizeof实际上没有被评估(所以解除引用从未实际发生)。

+5

事实上,如果它是'typeid'的操作数,并且它是一个'PolymorphClass *'类型的空指针,那么它将被解除引用*和*求值。它仍然是定义良好的(抛出'bad_typeid')。我真的不喜欢那种特殊的'typeid'治疗。 – 2010-04-28 16:42:15

+2

不允许NULL引用是不幸的。它展示了一些很酷的属性,但我想这只是使代码复杂化。 :(如果前提条件可用并且代码可以更好地验证,则可以安全地使用NULL引用。 – Adrian 2013-05-24 22:58:47

+1

sizeof()是一个变量类型的运算符,而不是值NULL指针的类型是 – jforberg 2015-06-09 17:40:34

1

解引用NULL指针是未定义的行为。在解引用它之前,你应该检查一个值是否为NULL。

2

取消引用NULL指针在C++标准中是显式未定义的行为,所以您看到的是实现特定的。在C++ 0X标准草案从1.9.4

复制(在这方面类似于先前标准):

某些其他操作被描述 本国际标准如 未定义(例如, 解引用空指针的效果)。 [注意:此国际标准 对 未定义行为的程序的行为没有要求。 - 注完]

+1

这很有趣,因为没有人能够显示标准解引用的地方空指针是明确的制造UB。标准在这里不正确。 – curiousguy 2011-11-29 02:53:28

+0

@curiousguy:8.3.2.5再一次暗指解引用空指针是未定义的事实。但你是对的,它的确如此,就好像它在别处解释过一样。无论如何,1.3.13解释了任何没有明确定义的行为都被认为是未定义的,所以情况可能如此。 – Gorpik 2011-11-29 10:39:30

+1

“8.3.2.5”顺便说一句,它拼写为8.3.2/5。没有8.3.2.5节。 “_任何未明确定义的行为都被认为是undefined_”你是对的:只有当指针指向一个对象时,才会定义一个指针。但是,如果标准明确地表明了这一点 - 将会稍微清晰一些 - 而且电子墨水将花费在这个非问题上。 – curiousguy 2011-11-29 11:19:24

1

为了完整起见,这个:http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232会谈具体这个问题。

+0

嗯...非常有创意的想法。因此,调用一个null'this'的成员函数是允许的!我不知道他们在吸烟。无论如何,7年后,这个疯狂的方向没有做任何事情。 – curiousguy 2011-11-29 03:03:17

+0

其实它不是,根据http://stackoverflow.com/a/2474021/399317(由于左值到右值的转换) – Kos 2012-08-23 17:49:22

+0

有趣的是,#232使用除零作为UB的一个例子,当许多C++实现隐含地包含了IEEE-754,IEEE-754定义了除正负零的效果。 *整数*除以零是UB,但该示例没有指定。 – supercat 2016-10-25 01:47:16

-2
int& ref = *ptr; 

上述声明实际上并没有对任何东西进行解引用。所以在使用ref(这是无效的)之前没有问题。

+4

废话。一元'*'实际上是**解引用运算符。它**实际上**执行取消引用操作。 – curiousguy 2011-11-29 02:54:50

+0

@curiousguy:我建议你编译并在反汇编器中看到代码。参考'ref'本质上是一个指针,所以上面的语句只是幕后的指针赋值。 – valdo 2011-11-29 15:20:01

+2

你误解了我。我不在乎生成了什么汇编代码。根据你的情况,'* ptr'是什么? – curiousguy 2011-11-29 16:23:49