【问题标题】:Avoid null pointer checks in C++避免在 C++ 中进行空指针检查
【发布时间】:2009-03-30 17:44:48
【问题描述】:

用例:

class B {

     int b;
     public:
         int getB() { 
               return b;
         }
 };

class A {
        B *b;
    public:
          int getB() {
              if (b ) {                      //How can I avoid the null check for b here
                  return b->getB();
              }
          }
  }

【问题讨论】:

  • 为什么要避免空指针检查?
  • 是的,很高兴知道您要实现什么...优化?更简洁的代码?
  • 空检查不是在错误的地方吗? getB() 需要返回 B,或者...... null(它还会返回什么?)

标签: c++ pointers


【解决方案1】:

如果 B 为 null 然后在 getB() 中,您期望会发生什么?如果它不是您的程序的有效状态,只需断言(b!= NULL)。如果是有效状态,则需要检查。

某些语言支持契约,因此您无需手动编写检查代码,但不幸的是 C++ 不支持。

【讨论】:

    【解决方案2】:

    解决方案 1:尽可能使用引用。

    解决方案 2:只需执行空指针检查并让编译器处理它们。如今,删除多余的空指针检查是一种标准优化。除了大部分冗余之外,它们没有捕获所有冗余。

    【讨论】:

      【解决方案3】:

      你有很多选择。这里有 5 个。

      解决方案 1: 将 B 的引用而不是指针传递给 A。

      虽然可以引用 NULL 对象。这真的很难做到,你不需要检查它。

      class A 
      {
        B &b;
      public:
        A (B& b_) : b(b_)
        {
        }
      
        int getB() 
        {
          return b.getB();
        }
      };
      

      解决方案 2:不要因此而牺牲类的关系设计,但它可能适用。

      从 B 派生类 A。然后您可以简单地调用 getB()。


      解决方案 3:也许您根本不应该使用指针,而只是让 B 成为 A 的成员。

      class A 
      {
        B b;
      
      public:
        int getB() 
        {
          return b.getB();
        }
      };
      

      解决方案 4:立即断言以避免以后的检查

      class A 
      {
        B *b;
      public:
        A (B* pb) : b(pb)
        {
          assert(pb != NULL);
        }
      
        int getB() 
        {
          return b->getB();
        }
      };
      

      解决方案 5:有一个你使用的默认 B

      class A 
      {
        B *pb;
        B defaultB;
      public:
        A () : pb(&defaultB)
        {
        }
      
        void setB(B* pb_)
        {
          if(pb != NULL)
            pb = pb_;
        }
      
        int getB() 
        {
          return pb->getB();
        }
      };
      

      【讨论】:

      • "虽然可以引用一个 NULL 对象" 不,在符合 C++ 的情况下不可能有一个空引用。
      【解决方案4】:

      正如 Brian Bondy 所提到的,参考是一种基于语言的方法。我知道的唯一另一个避免空检查的选项是Null Object Pattern。当然,这意味着对如何获取 B 对象进行更多的工作和控制。

      【讨论】:

        【解决方案5】:
        // case: you expect *b can be 0
        class A {
            B *b;
        public:
            int getB() {
                return b ? b->getB() : getDefaultValue();
            }
        }
        
        // case: there is shouldn't be a chance *b can be 0
        class AA {
            B *b;
        public:
            AA( B *bValue ):
                b(bValue)
            {
                assert( b );
            }
        
            int getB() {
                return b->getB();
            }
        };
        

        【讨论】:

          猜你喜欢
          • 2017-03-21
          • 2017-02-18
          • 2021-04-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-01
          • 2014-05-20
          相关资源
          最近更新 更多