【问题标题】:Is using NULL references OK?使用 NULL 引用可以吗?
【发布时间】:2010-10-14 01:33:44
【问题描述】:

我遇到了这段代码:

void f(const std::string &s);

然后是一个电话:

f( *((std::string*)NULL) );

我想知道其他人如何看待这种结构,它用于表示函数 f() 应该使用一些默认值(它计算出来的)而不是一些用户提供的值。

我不知道该怎么想,它看起来很奇怪,但你觉得这个结构怎么样?

【问题讨论】:

  • 不只是奇怪 - 邪恶。空引用是一个需要不惜一切代价避免的错误。

标签: c++


【解决方案1】:

没有。这是未定义的行为,可能导致代码执行任何操作(包括重新格式化硬盘、核心转储或侮辱您的母亲)。

如果您需要能够传递 NULL,则使用指针。接受引用的代码可以假定它引用了一个有效的对象。


附录:C++03 标准(ISO/IEC 14882, 2nd 2003 版)在 §8.3.2 “参考”第 4 段中说:

应初始化引用以引用有效对象 或功能。 [注意: 特别是,空引用不能存在于定义良好的程序中,因为 只有 创建此类引用的方法是将其绑定到通过取消引用空指针获得的“对象”, 这会导致未定义的行为。 如 9.6 中所述,引用不能直接绑定到位字段。 ]

[加粗表示强调]

【讨论】:

    【解决方案2】:

    使用 NULL 引用好吗?

    不,除非你不喜欢你的老板和你的工作;)

    这是非常糟糕的事情。最重要的参考点之一,它 不能为 NULL(除非你强制)

    【讨论】:

      【解决方案3】:

      我很好奇 - 函数 'f' 真的会检查这种情况吗?因为如果它没有,并且它尝试使用该字符串,那么当您尝试使用它时,这显然会崩溃。

      如果 'f' 确实检查了 NULL 的引用,那为什么不只是使用指针呢?是否有一些硬性规定,您不会使用指针,并且某些傻瓜遵守法律条文而不考虑其含义?

      我只是想知道...

      【讨论】:

      • 是的,f 实际上会检查这个条件( if (&s == NULL) ... )我认为他们使用了引用来保持接口的一致性。如果他们使用指针,那么他们就不能使用 f("hello") 无论如何,这只是我在其中找到的代码质量的另一个例子......
      【解决方案4】:

      对于这种情况,你可以制作“空对象”,它会起到零指针的作用

      class Foo
      {
      static Foo empty;
      public:
        static bool isEmpty( const Foo& ref )
        {
          return &ref==∅
        }
      }
      

      【讨论】:

        【解决方案5】:

        正如其他人已经说过的:引用必须是有效的。这就是为什么它是引用而不是指针的原因。

        如果你想让 f() 有一个默认行为,你可能想使用这个:

        static const std::string default_for_f;
        
        void f(const std::string &s = default_for_f)
        {
            if (&s == &default_for_f)
            {
                // make default processing
            }
            else
            ...
        }
        ...
        void bar()
        {
            f();              // call with default behavior
            f(default_for_f); // call with default behavior
            f(std::string()); // call with other behavior
        }
        

        您可以保留 f() 的默认参数。 (有些人讨厌默认参数。)

        【讨论】:

          【解决方案6】:

          你有时会在相当深奥的模板库代码中看到这样的结构,但只在 sizeof() 内部是无害的。

          假设您想知道类似函数的类型 F 的返回类型的大小,如果它作为参数传递了对类型 T 的引用(这两个都是模板参数)。你可以写:

          sizeof(F(T()))
          

          但是如果 T 碰巧没有公共默认构造函数怎么办?所以你改为这样做:

          sizeof(F(*((T *)0)))
          

          传递给sizeof 的表达式永远不会执行 - 它只是被分析到编译器知道结果大小的程度。

          【解决方案7】:
          f( *((std::string*)NULL) );
          

          这本质上是取消对 NULL 的引用,在大多数系统上它的 #defined 为 0。最后我检查了 0x00000000 是一个 invalid 内存地址用于执行任何操作。

          只是检查发生了什么

          if (std::string.length() > 0) ....
          

          【讨论】:

          • 你是对的,我只是在吹毛求疵:std::string().empty() 可以比 "std::string.length() > 0" 快
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-03-28
          • 1970-01-01
          • 1970-01-01
          • 2020-04-13
          • 2017-11-20
          • 2014-10-24
          • 1970-01-01
          相关资源
          最近更新 更多