В качестве предисловия к этому вопросу я должен сказать, что я программист на 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 (что также не очень удобно).
Итак, мой вопрос состоит из двух частей:
Какой удобный способ обработать неудачный поиск и какое возвращаемое значение будет полезно (исключение, NULL, пустая строка или что-то еще)?
В моем коде какой метод поиска карты более типичен для использования, когда вы ожидаете, что он может не найти ключ, at () и перехватить исключение, или найти и проверить итератор == map.end ()? (Эта часть вопроса — я просто пытаюсь изучить способ выполнения вещей на c ++).
Спасибо за любой совет!
На мой взгляд, лучше не возвращать указатели на содержимое карты, которую вы держите в секрете, так как указатели могут быть недействительными в случае изменения карты.
Я хотел бы, чтобы функция возвращала код успеха (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 варианта, которые я бы рассмотрел в зависимости от вашей готовности использовать повышение:
Вернуть указатель:
/* 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.
Эти методы поиска не требуют копирования значения с карты. Возврат через выходной параметр подразумевает создание копии значения. Я думаю, это зависит от ваших требований.