Возврат указателя на элемент, кэшированный в std :: map

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

std::map<std::string, Foo> _cache;

Мне нужно написать геттер для этого кэша, который возвращает ссылку, указатель, итератор или умный указатель на объект Foo, хранящийся в кэше. Я хочу, чтобы клиент мог обновлять объект Foo, если это требуется через геттер.

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

Какой тип возврата вы бы порекомендовали для моего геттера?

Я использую Boost и C ++ 98.

1

Решение

Похоже, вам нужно boost::optional<Foo&> возвращаемое значение (необязательные ссылки). Ваш код должен выглядеть так:

class YourCache {
std::map<std::string, Foo> _cache;
public:
boost::optional<Foo&> FooByName(const std::string& name)
{
std::map<std::string, Foo>::iterator itr = _cache.find(name);
if(_cache.end() == itr)
return boost::none;
return boost::optional<Foo&>(itr->second);
}
};
  • добытчик не бросает 🙂
  • уважает уже существующую реализацию _cache (вам не нужно менять ее для хранения умных указателей — или указателей в целом)
  • не дает прямого доступа к памяти в клиентском коде (как при возврате Foo *)
  • наилучшим образом выражает намерение («возвращаемое значение необязательно / может отсутствовать»)
  • предлагает явный и естественный интерфейс в клиентском коде:

Например:

// client code:
if (boost::optional<Foo&> result = YourCache.FooByName("FOO")) {
// only run if result is in cache
result->bar();
}
4

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

В вашем случае ссылки исключены из-за возможности возврата нулевого указателя. Итератор также не нужен, так как вы не можете проверить, действительно ли он указывает на элемент без доступа к функции .end () кеша, которая является закрытым членом. Если вы не предоставите интерфейс для тестирования, но это излишнее.

Единственный другой вариант — вернуть указатель. Тем не менее, таким образом, вы должны будете гарантировать, что указатель остается действительным в течение всего времени, в течение которого вызывающий абонент использует его. Один из способов сделать это — реализовать карту общих указателей, а именно:

std::map<std::string, boost::shared_ptr<Foo> > _cache;

Таким образом, даже если объект выбрасывается из кэша, вызывающая сторона все равно останется с действительным указателем. И shared_ptr может быть проверен как bool, поэтому в случае, если элемент не найден в кеше, вы можете вернуть пустой shared_ptr.

Но слишком мало известно о контексте кеша, чтобы сказать вам больше (например, нужна ли синхронизация и т. Д.).

2

Использовать повышение :: опционально удерживая ссылку Foo в качестве возвращаемого значения для получателя.

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector