tgoop.com/cxx95/14
Create:
Last Update:
Last Update:
#advice
Иммутабельные классы для объектов API
(Практический совет)
Допустим, что вы программируете показ рекламы фастфуда 🍟🍔🍕🥤 на сайтах. Надо показать топ-5 наиболее подходящих блюд. Формула оценки довольно сложная: зависит от региона юзера, доступности блюд в ближайшей точке, маркетинговых акций, текущего времени, etc.
Запросы приходят в API вашего сервиса. Пусть все данные для оценки представлены классами/структурами на C++.
Представим себе API-класс, который описывает одну из ближайших к юзеру точек питания. У него есть расстояние до юзера (чем дольше, тем меньше "вес" в оценке), загруженность, наличие разных блюд, акции, а также история посещений юзером.
struct Restaurant {Некоторыми данными объект "владеет" (как историей посещения), а на некоторые просто ссылается, потому что они общие для всех.
double Distance; // расстояние
double Occupancy; // загруженность
std::vector<Meal*> Meals; // доступные блюда
std::vector<Promo*> Promos; // акции
std::vector<Visit> VisitHistory; // история посещений
};
Здесь получаем проблему - пусть у нас где-то в программе лежат объекты блюд
std::vector<Meal> Meals
. Если мы создадим Restaurant
-ы, а потом добавим какое-то новое блюдо, то можно попасть на переаллокацию вектора, и в таком случае все ссылки Meal*
станут висячими.Можно обернуть объекты в умный указатель
std::vector<std::shared_ptr<Meal>> Meals
, но это не бесплатно и некрасиво.Есть способ, который решает несколько проблем - все API-классы нужно объявить non-copyable И non-movable. Какие будут плюсы:
(1) Объекты невозможно случайно передать по значению/скопировать
(2) Указатели на объекты живут столько же, сколько контейнер, где содержится объект.
Компилятор C++ не даст заиспользовать контейнер как
std::vector
, который потенциально сможет инвалидировать ссылки. Скомпилируется использование безопасного контейнера, например std::list
.BY C++95
Share with your friend now:
tgoop.com/cxx95/14