неупорядоченная карта: что вернуть, если ключа нет на карте?

в качестве предисловия к этому вопросу я должен сказать, что я программист Java и поэтому гораздо больше привык к семантике карт на Java, чем на C++. В Java это довольно распространено и ожидается get null возвращается при поиске ключа на карте. Я перевожу часть нашего кода на c++ и пытаюсь найти способ работы c++ при взаимодействии с unordered_map.

в частности, у меня есть класс, который содержит unordered_map. Вместо разоблачения карте непосредственно в клиентский код у меня есть 2 функции-оболочки, одна для размещения пары ключ/значение на карте, а другая для получения значения для указанного ключа, i.e:

void set_tag_value(string tag, string value);

string& get_tag_value(string tag);

если я использую unordered_map.at() чтобы получить значение, то он выдаст исключение, которое мой код должен был бы поймать, или, альтернативно, позволить ему распространяться на клиентский код. (Распространение исключения на Кажется мне недружелюбным).

возможно, альтернативой было бы изменить возвращаемое значение на string* введите и верните NULL, если не найдено (что является способом Java), но затем пользователь должен проверить NULL (что также не так дружелюбно).

Итак, мой вопрос состоит из двух частей:

  1. что такое удобный для разработчика способ обработки неудачного поиска и какое возвращаемое значение было бы полезно (исключение, NULL, пустая строка или что-то еще)?

  2. внутри моего кода, какой метод поиска карты более типичен для использования, когда вы его ожидаете может не найти ключ, исключение at() и catch или найти и проверить iterator == map.конец()? (Эта часть вопроса заключается в том, что я просто пытаюсь изучить способ работы на c++).

Спасибо за любой совет!

2 ответов


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

Я хотел бы, чтобы функция возвращала код успеха (bool) и передайте ссылку на строку, чтобы фактически вернуть значение, если оно найдено. Например,

bool get_tag_value(const string& tag, string& value)
{
    auto t = my_map.find(tag);
    if (t == my_map.end()) return false;
    value = t->second;
    return true;
}

обратите внимание, что в то время как unordered_map::at() будет бросать, если ключ не найден,unordered_map::find() возвращает неверный итератор (unordered_map::end()) - таким образом, вы можете избежать обработки исключения таким образом.

если вы хотите придерживаться возврата строки, просто верните пустую строку (return string();), если ключ не найден.


Это 2 варианта, которые я бы рассмотрел в зависимости от вашей готовности использовать boost:

возвращает указатель:

/* const? */ string* get_tag_value_ptr(const string& tag)
{
    auto it = theMap.find(tag);
    if (it != theMap.end()) {
        return &it->second;
    }

    return nullptr;
}

возврат необязательной ссылки:

boost::optional</* const? */ string&> get_tag_value_opt(const string& tag)
{
    auto it = theMap.find(tag);
    if (it != theMap.end()) {
        return it->second;
    }

    return boost::none;
}

надеюсь, у нас будет std::optional скоро, хотя он был отложен с C++14.

эти методы извлечения не требуют необходимости копировать значение с карты. Возврат через параметр out подразумевает создание копии значения. Я предполагаю, что это зависит от ваших требований.