引用不能为NULL或者它可以为NULL?

时间:2010-01-29 20:52:24

标签: c++ oop

我从维基百科上读到:

  

“引用不能为null,而指针可以为;每个引用都指某个对象,尽管它可能有效也可能无效。“

但是我不相信因为下面的代码看看它编译器没有给出错误:

class person
{
public:
virtual void setage()=0;
};
main()
{
person *object=NULL;
person &object1=*object;
}

请详细说明这一点。

7 个答案:

答案 0 :(得分:20)

在您的代码中:

person *object=NULL;
person &object1=*object;

您取消引用NULL指针,因此您将获得未定义的行为。要回答你的问题,就没有NULL引用这样的东西。

为了解决问题的其他部分,仅仅因为程序编译,不能保证它是正确的或它会起作用。 C ++编译器甚至不需要尝试诊断代码所包含的错误类型。

答案 1 :(得分:9)

person &object1=*object与说person &object1=NULL不是一回事。可能编译器不够聪明,无法发现您正在解除引用空指针,但无论如何您都会遇到运行时错误。所以它们仍然是真实的;)

答案 2 :(得分:4)

你可以有一个空引用,不知道为什么有人会这么说,这是一些操作的令人讨厌的副作用。你不能直接创建一个。

答案 3 :(得分:3)

会导致程序崩溃。你试过试试吗? 执行*对象将取消引用空指针,因此实际上您的引用永远不会被赋值。

答案 4 :(得分:2)

好吧,你可以在C ++中做任何想要的事情。另一个例子:

person &object1 = *( reinterpret_cast<person*>(0) );

除了你提到的情况之外,你在上面的案例中调用了一个未定义的行为!

答案 5 :(得分:1)

clang 3.5甚至警告可能稍后对引用进行NULL检查:

/tmp/person.C:11:6: warning: reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to
      always convert to true [-Wundefined-bool-conversion]
if (&object1) {}
~~   ^~~~~~~
1 warning generated.

答案 6 :(得分:0)

gcc8会对此发出警告:

  

警告:编译器可以假定'object1'的地址永远不会为NULL [-Waddress]

一个小演示:

#include <iostream>

class person
{
    public:
        virtual void setage()=0;
};

int main()
{
    person *object=NULL;
    person &object1=*object;

    if (&object1 == NULL) {
        std::cout << "NULL object1" << std::endl;
    }

    if (!(&object1)) {
        std::cout << "NULL object1 " << std::endl;
    }
}

编译并运行输出:

  

g ++ -std = c ++ 2a -pthread -fgnu-tm -O2 -Wall -Wextra -pedantic -pthread   -pedantic-errors main.cpp -lm -latomic -lstdc ++ fs && ./a.out

     

main.cpp:在函数'int main()'中:

     

main.cpp:14:18:警告:编译器可以假定   'object1'永远不会为NULL [-Waddress]

 if (&object1 == NULL) {

              ^
     

main.cpp:18:19:警告:编译器可以假定   'object1'永远不会为NULL [-Waddress]

 if (!(&object1)) {

               ^
     

NULL object1

     

NULL object1