Избегайте проверок нулевых указателей в C ++ - PullRequest
0 голосов
/ 30 марта 2009

Вариант использования:

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();
              }
          }
  }

Ответы [ 5 ]

8 голосов
/ 30 марта 2009

Что вы ожидаете, если B будет нулевым, тогда в getB ()? Если это не допустимое состояние для вашей программы, просто подтвердите (b! = NULL). Если это действительное состояние, вам нужен чек.

Некоторые языки поддерживают контракты, поэтому вам не нужно писать код проверки вручную, но, к сожалению, C ++ этого не делает.

6 голосов
/ 30 марта 2009

Решение 1. Используйте ссылки, если это возможно.

Решение 2. Просто выполните проверку нулевого указателя и дайте компилятору позаботиться о них. Удаление избыточных проверок нулевого указателя в наши дни является стандартной оптимизацией. Они не улавливают все, кроме большей части избыточности.

2 голосов
/ 30 марта 2009

У вас есть много вариантов. Вот 5.

Решение 1: Передать ссылку B на A вместо указателя.

Хотя возможно иметь ссылку на объект NULL. Это действительно сложно сделать, и вам не нужно проверять это.

class A 
{
  B &b;
public:
  A (B& b_) : b(b_)
  {
  }

  int getB() 
  {
    return b.getB();
  }
};

Решение 2: Не жертвуйте этим дизайном отношений ваших классов, но это может быть применимо.

Получите класс A из B. Тогда вы можете просто вызвать 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();
  }
};
0 голосов
/ 30 марта 2009
// 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();
    }
};
0 голосов
/ 30 марта 2009

Как упоминал Брайан Бонди, ссылка - это один из языковых способов сделать это. Единственная другая опция, которую я знаю, чтобы избежать пустых проверок, это Null Object Pattern . Это, конечно, подразумевает большую работу и контроль над тем, как вы получаете объект B.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...