Возвращает объект "NULL", если результат поиска не найден


Я довольно новичок в C++, поэтому я склонен проектировать с большим количеством Java-isms, пока я учусь. Во всяком случае, в Java, если бы у меня был класс с методом 'search', который вернул бы объект T С Collection< T > что соответствует определенному параметру, я бы вернул этот объект, и если объект не был найден в коллекции, я бы вернул null. Тогда в моей вызывающей функции я бы просто проверил if(tResult != null) { ... }

в C++, я узнаю, что я не могу вернуть a null значение, если объект не существует. Я просто хочу вернуть "индикатор" типа T, который уведомляет вызывающую функцию о том, что объект не найден. Я не хочу делать исключение, потому что это не исключительное обстоятельство.

вот как выглядит мой код прямо сейчас:

class Node {
    Attr& getAttribute(const string& attribute_name) const {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            return NULL; // what should this be?
    }

private:
    vector<Attr> attributes;
}

как я могу изменить его, чтобы я мог дать такой маркер?

8 85

8 ответов:

в C++, ссылки не могут быть null. Если вы хотите дополнительно вернуть null, если ничего не найдено, вам нужно вернуть указатель, а не ссылку:

Attr *getAttribute(const string& attribute_name) const {
   //search collection
   //if found at i
        return &attributes[i];
   //if not found
        return nullptr;
}

в противном случае, если вы настаиваете на возврате по ссылке, то вы должны бросать исключение, если атрибут не найден.

(кстати, я немного беспокоюсь о том, что ваш метод const и возврат не

здесь есть несколько возможных ответов. Вы хотите вернуть то, что может существовать. Вот несколько вариантов, начиная от моего наименее предпочтительного до наиболее предпочтительного:

  • возврат по ссылке, и сигнал не может найти исключение.

    Attr& getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            throw no_such_attribute_error;
    }

вполне вероятно, что не найти атрибуты является нормальной частью выполнения, и, следовательно, не очень исключительным. Обработка для этого будет шумной. Значение null не может быть возвращен, потому что это неопределенное поведение, чтобы иметь нулевые ссылки.

  • вернуть по указателю

    Attr* getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return &attributes[i];
       //if not found
            return nullptr;
    }

легко забыть проверить, будет ли результат getAttribute ненулевым указателем и является простым источником ошибок.

  • использовать импульс.Необязательно

    boost::optional<Attr&> getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            return boost::optional<Attr&>();
    }

a boost:: optional означает именно то, что здесь происходит, и имеет простые методы для проверки того, являются ли такие атрибут был найден.


Примечание стороны: std:: optional недавно был проголосован в C++17, так что это будет "стандартная" вещь в ближайшем будущем.

Вы можете легко создать статический объект, который представляет собой нулевой возврат.

class Attr;
extern Attr AttrNull;

class Node { 
.... 

Attr& getAttribute(const string& attribute_name) const { 
   //search collection 
   //if found at i 
        return attributes[i]; 
   //if not found 
        return AttrNull; 
} 

bool IsNull(const Attr& test) const {
    return &test == &AttrNull;
}

 private: 
   vector<Attr> attributes; 
};

и где-то в файле с исходным кодом:

static Attr AttrNull;

Если вы хотите NULL возвращаемое значение, вы должны использовать указатели вместо ссылок.

ссылки сами по себе не могут быть NULL.

(примечание к будущим плакатам комментариев: Да, вы можете иметь адрес ссылки быть нулевым, если вы действительно действительно пытаетесь).

смотрите мой ответ здесь для списка различий между ссылками и указателями.

Как вы поняли, что вы не можете сделать это, как вы сделали в Java (или C#). Вот еще одно предложение, вы могли бы передать ссылку на объект в качестве аргумента и возвращает значение bool. Если результат найден в вашей коллекции, вы можете назначить его переданной ссылке и вернуть "true", в противном случае вернуть "false". Пожалуйста, рассмотрите этот код.

typedef std::map<string, Operator> OPERATORS_MAP;

bool OperatorList::tryGetOperator(string token, Operator& op)
{
    bool val = false;

    OPERATORS_MAP::iterator it = m_operators.find(token);
    if (it != m_operators.end())
    {
        op = it->second;
        val = true;
    }
    return val;
}

функция выше должна найти оператор против ключа "токен", если он находит тот, который он возвращает true и присвоить значение параметру Operator & op.

код вызывающего абонента для этой процедуры выглядит так

Operator opr;
if (OperatorList::tryGetOperator(strOperator, opr))
{
    //Do something here if true is returned.
}

причина, по которой вы не можете вернуть NULL здесь, заключается в том, что вы объявили свой тип возврата как Attr&. Трейлинг & делает возвращаемое значение "ссылкой", которая в основном является гарантированным указателем not-to-be-null на существующий объект. Если вы хотите иметь возможность возвращать null, измените Attr& до Attr*.

вы не можете вернуть NULL потому что возвращаемый тип функции является объектом reference, а не pointer.

вы можете попробовать это:

return &Type();