【问题标题】:Reference pointing to a Null-object指向空对象的引用
【发布时间】:2011-09-19 05:58:51
【问题描述】:

我看到了这个讨论 - Checking for a null object in C++,我很惊讶没有人谈论什么时候引用可以指向一个空对象。在我们的代码中,我们经常使用空对象。有如下函数返回 nullObj。

const Obj&  
nullObj()  
{  
   static obj* nullPtr = NULL;   
   return static_cast<  const Obj&>(*nullPtr);    
}  

实际上,当我再次查看代码提出这个话题时,我对上面的代码是如何工作的有一些疑问:

  1. 怎么可能做到*nullPtr - 是不是因为 nullPtr 是一个静态对象,它在堆上分配内存,因此保证有一些空间和

  2. 1234563

【问题讨论】:

  • 糟糕...没注意到。哦,好吧,给他最后一个。
  • 请让我们都知道您使用什么软件,这样我们就可以避免它。 “我们经常使用空对象”有点危险,因为不存在这样的事情......
  • 仍然是个好问题,恕我直言。每个人都应该被允许问这种“我要朝自己的脚开枪”的问题。
  • 来自您链接的问题:stackoverflow.com/questions/2099882/…
  • @Dave:或者在这种情况下,“我已经多次向自己的脚开枪,但还没有摔倒”。

标签: c++ pointers object reference null


【解决方案1】:

(i) 怎么可能做到 *nullPtr - 是不是因为 nullPtr 是一个静态对象,它被分配了内存 堆,因此它被保证 分配了一些空间和地址 取消引用?

不,这是因为nullPtr是一个初始化为NULL的指针,它根本不是一个对象。

(ii) 因为我们返回的是 const 对 obj 的引用,编译器是否创建 一个临时对象(对于某种 nullObj??) 或将 const 引用 充当 nullPtr 本身的别名?

它将是位于内存地址 NULL 的对象的别名。即:当您实际访问此引用对象的任何成员时 - 您将得到 whatever (通常是访问冲突,如果系统足够智能,但它实际上可以是任何东西,行为是未定义的)。

【讨论】:

  • 从技术上讲,未定义的是取消引用,而不是引用。
  • @Tom,这不是我说的吗?:-)
  • 我想,当您尝试通过参考访问成员时,您谈到了更多。但关键是仅仅获取引用已经是未定义的了。
  • 这是否意味着对 NULL 指针的引用是无效的——即使是象征性地使用它?我们总是检查引用以查看它是否不为空,然后仅在引用指向有效对象时才使用该引用。
  • @srikrish - @Tom 想说的是,仅仅创建这样的引用可能会导致未定义的行为。根据 C++ 规范,他是正确的,尽管当你尝试读/写它时,“未定义的行为”可能真的会起作用,但你不应该转发它,因为没有人向你保证它会起作用,如果它会 - 在不同的编译器或编译器版本下不会被破坏。简而言之 - 你应该永远做你想做的事。
【解决方案2】:

我很惊讶没有人谈论什么时候引用可以指向一个空对象。

从不。

(i) 怎么可能做 *nullPtr - 是不是因为 nullPtr 是一个静态对象,它在堆上分配内存,因此保证为 deref 分配一些空间和地址?

不是。您正在取消引用一个空指针,它正在调用未定义的行为。

(ii) 由于我们返回对 obj 的 const 引用,编译器会创建一个临时对象(对某种 nullObj 吗??)还是 const 引用会充当 nullPtr 本身的别名?

没有。在这个阶段,编译器被允许产生鼻守护进程或黑洞。如果你非常幸运,你会遇到分段错误或其他类型的访问冲突。

不要这样做

【讨论】:

  • 我明白 - 所以 obj& 是对 NULL 指针的引用,并且这里没有创建对象。这是否意味着 nullPtr 永远不会分配任何内存空间?
  • @srikrish:不,您的obj&amp; 是对不存在的对象的引用。你有一个空指针,这意味着它没有指向一个有效的对象。然后,您尝试引用这个不存在的对象。在取消引用之前,NULL 指针没有任何问题,因为取消引用不指向有效对象的指针当然是未定义的。您确实 not 引用了一个空指针,这将是有效的,看起来像这样:T* ptr = NULL; T*&amp; ref = ptr;
【解决方案3】:

我很惊讶没有人谈论什么时候引用可以指向一个空对象

那是因为它不能在正确的程序中。

取消引用空指针的函数具有未定义行为。允许编译器发出代码,例如,此时会导致崩溃。

但是,UB 的一种可能效果是代码执行了人们认为它会执行的操作。因此可能会发生空引用。我从来没有遇到过,但是如果遇到了,那就说明代码有严重的逻辑错误。

您展示的 null-object-reference 函数的所有使用都是逻辑错误。

您最好了解这些用途并修复问题。 ;-)

干杯,

【讨论】:

  • 请看这篇关于空对象的文章-citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.107.9051(针对JAVA、UML)。但是空对象的概念似乎是有效的——就像 unix 使用 /dev/null。这里的目的是通过引用空指针为 c++ 中的空对象提供封装。但现在我看到取消引用 nullPtr 会导致 UB。 c++ 是否提供了更好的方法来实现空对象?
  • @sikrish:C++ 指针可以为空。这是使用指针作为参数的一个主要原因:它支持 null。引用不能为空。这是使用引用作为参数的主要原因:它们不能为空。干杯&hth.,
  • 有趣的是,我在测试代码中遇到了这种构造。一个微不足道的模板函数几乎像 OP 一样返回任何类型的引用,总是对称为“空对象”的自相矛盾。这些引用用作被测对象的构造函数参数;特定测试的代码路径当然永远不会引用那个“空对象”。不使用指针的基本原理正是在生产代码中保证有一个对象。类似的推理不仅适用于具有默认构造函数。糟糕但方便,可在 VS 和我们 90 年代中期的编译器中使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-07
  • 2021-07-19
  • 1970-01-01
  • 1970-01-01
  • 2013-02-03
相关资源
最近更新 更多