Предположим, мы пишем огромную многопользовательскую онлайн-игру, которая должна поддерживать в памяти сотни тысяч или миллионы экземпляров следующего класса:
В таких средах ресурсы памяти драгоценны, поэтому мы ищем способы сделать<user_entry>максимально компактным. Как правило, среди пользователей сообщества существует очень высокий уровень повторения имен и фамилий, поэтому очевидная оптимизация заключается в перемещении объектов<user_entry::first_name>и<user_entry::last_name>в общий репозиторий, где дубликаты избегают, и оставлении ссылок на них внутри<user_entry>. Именно это и подстегнуло. Flyweight делает это самым простым способом для программиста:
Повышаю. Flyweight автоматически выполняет оптимизацию, только что описанную за кулисами, так что чистый эффект этого изменения заключается в том, что использование памяти программы уменьшается на коэффициент, пропорциональный уровню избыточности среди имен пользователей.
<flyweight<std::string>>ведет себя во многих отношениях как<std::string>; например, следующий код работает без изменений после переопределения<user_entry>:
// flyweight<T> can be constructed in the same way as T objects can,
// even with multiple argument constructorsuser_entry::user_entry(constchar*f,constchar*l,inta,...):first_name(f),last_name(l),age(a),...{}// flyweight classes have relational operators replicating the
// semantics of the underyling typeboolsame_name(constuser_entry&user1,constuser_entry&user2){returnuser1.first_name==user2.first_name&&user1.last_name==user2.last_name;}// flyweight<T> provides operator<< and operator>> internally
// forwarding to T::operator<< and T::operator>>std::ostream&operator<<(std::ostream&os,constuser_entry&user){returnos<<user.first_name<<" "<<user.last_name<<" "<<user.age;}std::istream&operator>>(std::istream&is,user_entry&user){returnis>>user.first_name>>user.last_name>>user.age;}
Кроме того,<flyweight<T>>конвертируется в<const T&>, либо неявно, либо через функцию<get>члена:
std::stringfull_name(constuser_entry&user){std::stringfull;full.reserve(user.first_name.get().size()+// get() returns the underlyinguser.last_name.get().size()+1);// const std::string&full+=user.first_name;// implicit conversion is used herefull+=" ";full+=user.last_name;returnfull;}
Наиболее важным ограничением, которое следует учитывать при замене класса эквивалентным весом, является тот факт, что весы не являются изменчивыми: поскольку несколько объектов в весе могут иметь одинаковое значение представления, изменение этого значения недопустимо. С другой стороны, объектам с массой тела могут быть присвоены новые значения:
В общем, интерфейс<flyweight<T>>предназначен для того, чтобы сделать переход от простого<T>как можно более простым. Проверьте ссылкудля получения дополнительной информации об интерфейсе шаблона класса<flyweight>. В разделепримероврассматриваются некоторые общие сценарии использования Boost. Весом.
<flyweight<T>>может быть сериализовано с помощьюБиблиотеки усиленной сериализациидо тех пор, пока базовая<T>является сериализуемой. Поддерживаются как обычные, так и XML-архивы. Для того, чтобы увеличить Возможности серийизации с массой полёта должны включать конкретный заголовок<"boost/flyweight/serialize.hpp">.
То же самое, что и Boost. Flyweight уменьшает потребление памяти из-за внутреннего обмена дублирующими значениями, сериализация<flyweight>s также может привести к уменьшению архивных файлов, поскольку общее значение сохраняется только один раз, а связанные с ним<flyweight>s сохраняются в качестве ссылок на него. Эта политика соблюдается, даже если<flyweight>основной тип не отслеживаетсяBoost.Serialization.
См.пример 6в разделе примеров для иллюстрации использования Boost. Возможности серийного производства.
Чтобы<flyweight<T>>был мгновенным,<T>должен быть<Assignable>,<Equality
Comparable>и должен взаимодействовать сBoost.Hash. Первое требование, вероятно, выполняется без каких-либо дополнительных усилий со стороны пользователя, не так как два других, за исключением наиболее распространенных основных типов C++ и стандартной библиотеки. Равенство и хеширование<T>используются внутри<flyweight<T>>внутренней фабрики для поддержания общего хранилища уникальных<T>значений, упоминаемых объектами с массой тела. Проконсультируйтесь с Boost. Хеш-документацияраздело расширении этой библиотеки для пользовательских типов данных.
Как мы видели, требования к равенству и хешированию<T>налагаются конкретным типомфабрики по производству легкого веса, используемой внутри<flyweight<T>>. Позже мы увидим, как пользователь может настроить эту фабрику, чтобы использовать равенство и хеш-предикаты, отличные от по умолчанию, или даже переключиться на совершенно другой тип фабрики, который может налагать другие требования на<T>, как описано в разделенастройки Boost.Flyweight.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.