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

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

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

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 () и перехватить исключение, или найти и проверить итератор == map.end ()? (Эта часть вопроса — я просто пытаюсь изучить способ выполнения вещей на c ++).

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

12

Решение

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

Я хотел бы, чтобы функция возвращала код успеха (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();) если ключ не найден.

13

Другие решения

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

Вернуть указатель:

/* 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.

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

1

По вопросам рекламы [email protected]