【问题标题】:How do I test whether a reference is NULL?如何测试引用是否为 NULL?
【发布时间】:2011-11-07 00:47:28
【问题描述】:

我想检查某些东西是否为空,例如:

string xxx(const NotMyClass& obj) {
  if (obj == NULL) {
     //...
  }
}

但是编译器对此抱怨:== 有 5 种可能的重载。

所以我尝试了这个:

  if (obj == static_cast<NotMyClass>(NULL)) {

这会崩溃,因为 NotMyClass== 重载无法处理空值。

编辑:每个人都告诉我它不能为 NULL,我肯定会在我的调试器中得到一些 NULL 的东西:

【问题讨论】:

  • obj 是引用,而不是指针。您无法将其与 NULL 进行比较。
  • C++ 不是 C 或 Java。这里的答案很好,但你也可以从阅读 C++ 中的指针和引用中受益。
  • 我非常怀疑你会因为那个条件而“崩溃”。
  • @Tomalak 在我的调试器中,我看到它试图在该引用上执行 obj.something() 。它确实会崩溃。
  • 检查这种情况唯一明智的做法是if(&amp;obj==NULL),但无论如何它都没有意义,因为如果你得到一个“NULL参考”,这意味着您的应用程序中存在逻辑错误(您已经取消引用 NULL 指针来创建此类引用,因此您已经处于未定义行为的境地)。正因为如此,编译器也可以优化掉这样的检查,因为它知道 NULL 引用不存在(因为 routinely does for NULL 检查已经被取消引用的指针)。

标签: c++ operator-overloading reference


【解决方案1】:

在格式良好的 C++ 程序中,引用永远不会是 NULL(更准确地说,您引用的对象的地址可能永远不会是 NULL)。

因此,答案不仅是“不,没有办法”,而且推论是“这毫无意义”。


您关于 C 的陈述也毫无意义,因为 C 没有引用。

而对于 Java,它的“引用”在很多方面都更像 C++ 指针,包括这一点。

比较不同语言之间的这种特定行为是一件愚蠢的事情。


如果您需要这种“可选对象”行为,那么您正在寻找指针:

std::string xxx(const NotMyClass* ptr) {
  if (ptr == NULL)
     throw SomeException();

  const NotMyClass& ref = *ptr;
  /* ... */
}

但是考虑一下你是否真的需要这个;如果你真的这样做,一个不错的选择可能是boost::optional

【讨论】:

  • 在堆栈的更深处它是一个指针,并且有人将它转换为引用。我把它作为参考。它是“NULL”。
  • @deliciousirony:程序在人取消引用该空指针的那一刻调用 UB;之后的任何事情都是愚蠢的。您看到实现泄漏纯属偶然(有点)
  • @deliciousirony:我想你的意思是s/static/call stack/
【解决方案2】:

你问的没有意义。 C++ 中的引用永远不能为“null”,因为它们只能通过为现有对象设置别名来创建,并且它们不能被重新绑定。一旦引用了x,就总是引用x

(如果原始对象的生命周期在引用之前结束,则引用可能会变成“悬空”,但这是一个编程错误,而不是可检查的运行时条件。)

【讨论】:

    【解决方案3】:

    您不需要对此进行测试,因为 C++ 中的引用不能为 NULL。 Pointers 可以为 NULL,但这里没有使用它们。

    【讨论】:

      【解决方案4】:

      正如其他人所说,定义良好的代码永远不会有 NULL 引用,因此测试它们不是您的责任。

      这并不严格意味着它们从未在实践中创建(但希望在中间代码中,而不是在生产代码中)。在某些编译器中,虽然绝对不是标准的 C++,但有可能获得地址为 NULL 的引用:

      int * p = NULL;
      int & x = *p;
      

      通常(还)不会崩溃,尽管按照 C++ 标准,它在第二行之后是不确定的行为。这是引用通常在“幕后”使用指针实现的副作用。当有人使用 x 时,它可能会在稍后崩溃。

      如果你想调试这样的情况,你可以测试一下x的地址是否不为NULL:

      #include <cassert>
      // ...
      assert(&x != NULL);
      

      【讨论】:

      • +1 好答案,尽管可能值得指出的是,“引用为NULL”这句话是错误的;它是我们正在讨论的引用对象的地址(尽管不存在!)。
      【解决方案5】:

      正如人们所说,C++ 中的引用永远不应该为空(NULL 或 nullptr),但是仍然有可能获得空引用,尤其是在您进行一些邪恶的强制转换时。 (很久以前,当我不知道更好的时候,我做了这样的事情。)

      要测试引用是否为空(NULL 或 nullptr),请将其转换为指针,然后进行测试。所以:

      if (&obj == nullptr)
      

      是您有效寻找的。​​p>

      但现在既然你知道怎么做,不要。假设引用永远不能为空,如果它们是空的话,让应用程序崩溃,因为到那时肯定有其他事情发生了可怕的错误,程序应该被终止。

      【讨论】:

      • 在格式良好的程序中是不可能的;当您获得对不存在的对象的“引用”时,您的 UB 就开始了。之后的任何事情都是愚蠢的。
      • int&amp; foo() { return (int&amp;)*((int*)0); } 将创建一个 NULL 引用,如果您尝试对返回值执行任何操作(除了获取指针),它将崩溃。
      • 不,没有“空引用”这样的东西。你所拥有的是一个用看起来有点像 C++ 的东西编写的程序,它包含一些看起来像对不存在的对象的引用的东西。
      • 是的,它无效,但它仍然意味着它可以完成并且会编译。但是,当运行时,它会一有机会就崩溃。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-27
      • 2011-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多