此代码似乎实现了在C++中返回空引用

Chu*_*uck 13 c++

我的C++知识有些零碎.我正在重新编写一些代码.我更改了一个函数来返回对类型的引用.在里面,我根据传入的标识符查找对象,然后返回对象的引用(如果找到).当然,如果我找不到对象,我会遇到要返回的问题,并且在环顾网络时,许多人声称在C++中返回"空引用"是不可能的.基于这个建议,我尝试了返回成功/失败布尔值的技巧,并使对象引用为out参数.但是,我遇到了需要初始化我将作为实际参数传递的引用的障碍,当然也没有办法做到这一点.我退回到通常只返回指针的方法.

我问了一位同事.他经常使用以下技巧,这是最新版本的Sun编译器和gcc都接受的:

MyType& someFunc(int id)
{
  // successful case here:
  // ...

  // fail case:
  return *static_cast<MyType*>(0);
}

// Use:

...
MyType& mt = somefunc(myIdNum);

if (&mt) // test for "null reference"
{
  // whatever
}
...
Run Code Online (Sandbox Code Playgroud)

我一直在维护这个代码库,但我发现我没有足够的时间来查找我想要的语言的小细节.我一直在挖掘我的参考书,但这个答案让我望而却步.

现在,我在几年前开设了一门C++课程,其中我们强调在C++中,一切都是类型,所以我在考虑事情时会尽量记住这一点.解构表达式:" static_cast <MyType >(0);",在我看来,我们确实采用了字面零,将其转换为指向MyType的指针(使其成为空指针),然后应用解除引用运算符分配给引用类型(返回类型)的上下文,它应该为我提供对指针指向的同一对象的引用.这看起来像是向我返回一个空引用.

任何解释为什么这个工作(或为什么不应该)的建议将不胜感激.

谢谢,查克

Jam*_*lis 16

此代码不起作用,但它似乎可行.该行取消引用空指针:

return *static_cast<MyType*>(0);
Run Code Online (Sandbox Code Playgroud)

零,强制转换为指针类型,导致空指针; 然后使用一元 - 取消引用此空指针*.

取消引用空指针会导致未定义的行为,因此您的程序可能会执行任何操作.在您描述的示例中,您将获得一个"空引用"(或者,它似乎得到一个空引用),但是对于您的程序崩溃或其他任何事情发生也是合理的.

  • 一元*运算符不会取消引用指针.从n2521(草案我知道,但我相信最新的相同).第5.3.1-1节:一元*运算符的结果是一个引用对象或函数的左值.这就是官方名称是"一元*运算符"而不是"解引用运算符"的原因 (2认同)
  • @Martin York:我知道标准不会调用`*`_derefence_但不是"为指针指向的对象形成左值"大多数人通过derefencing的意思?在标准中关于"一元*"的说明中,它表示"指向不完整类型的指针可以被取消引用",这似乎意味着应用一元*是执行解除引用的一种方法. (2认同)

Com*_* 10 12

我同意其他海报,你的例子的行为是未定义的,真的不应该使用.我在这提供一些替代品.他们每个人都有利弊

  1. 如果找不到该对象,则抛出一个在调用层中捕获的异常.
  2. 创建一个全局可访问的实例,MyType它是一个简单的shell对象(即static const MyType BAD_MYTYPE),可用于表示一个坏对象.
  3. 如果可能不经常找到该对象,则可以通过引用将该对象作为参数传递,并返回bool或其他指示成功/失败的错误代码.如果找不到对象,则不要在函数中指定它.
  4. 使用指针代替并在返回时检查0.
  5. 使用Boost智能指针,它允许检查返回对象的有效性.

我个人的偏好是前三个中的一个.


R S*_*hko 9

这是未定义的行为.因为它是未定义的行为,它可能在您当前的编译器上"工作",但如果您升级/更改编译器,它可能会中断.

从C++ 03规范:

8.3.2/4 ......应初始化参考以引用有效的对象或功能.[注意:特别是,在明确定义的程序中不能存在空引用,因为创建这样的引用的唯一方法是将它绑定到通过解引用空指针获得的"对象",这会导致未定义的行为.


T.E*_*.D. 5

如果您与return-a-reference接口结合,那么如果您找不到给定ID的对象,RightThing®将抛出异常.至少这种方式,你的可怜的用户可以捕获条件陷阱.

如果您在它们上取消引用空指针,则它们没有定义的方法来处理错误.