C++ Boost Flyweight库使用介绍

 更新时间:2022年12月05日 10:51:02   作者:无水先生  
Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称

一、说明

以下库用于设计模式。

  • Boost.Flyweight 有助于在程序中使用许多相同的对象并且需要减少内存消耗的情况。
  • Boost.Signals2 使得使用观察者设计模式变得容易。这个库被称为 Boost.Signals2 因为它实现了信号/槽的概念。
  • Boost.MetaStateMachine 使得将状态机从 UML 转移到 C++ 成为可能。

本节内容

66. Boost.Flyweight

67. Boost.Signals2

68. Boost.MetaStateMachine

二、库Boost.Flyweight

Boost.Flyweight 

Boost.Flyweight 是一个可以轻松使用同名设计模式的库。当许多对象共享数据时,享元有助于节省内存。使用这种设计模式,不是在对象中多次存储相同的数据,而是将共享数据保存在一个地方,所有对象都引用该数据。虽然您可以使用例如指针来实现此设计模式,但使用 Boost.Flyweight 更容易。

示例 66.1。没有 Boost.Flyweight 的十万个相同的字符串

#include <string>
#include <vector>
struct person
{
  int id_;
  std::string city_;
};
int main()
{
  std::vector<person> persons;
  for (int i = 0; i < 100000; ++i)
    persons.push_back({i, "Berlin"});
}

Example 66.1 

示例 66.1 创建了十万个 person 类型的对象。 person 定义了两个成员变量:id_ 标识人,city_ 存储人们居住的城市。在这个例子中,所有人都住在柏林。这就是为什么 city_ 在所有十万个对象中都设置为“Berlin”。因此,该示例使用十万个字符串,所有字符串都设置为相同的值。使用 Boost.Flyweight,可以使用一个字符串——而不是数千个——并且可以减少内存消耗。

示例 66.2。使用 Boost.Flyweight 一个字符串而不是十万个字符串

#include <boost/flyweight.hpp>
#include <string>
#include <vector>
#include <utility>
using namespace boost::flyweights;
struct person
{
  int id_;
  flyweight<std::string> city_;
  person(int id, std::string city) : id_{id}, city_{std::move(city)} {}
};
int main()
{
  std::vector<person> persons;
  for (int i = 0; i < 100000; ++i)
    persons.push_back({i, "Berlin"});
}

要使用 Boost.Flyweight,请包含 boost/flyweight.hpp,如示例 66.2 所示。 Boost.Flyweight 提供了额外的头文件,仅当您需要更改详细的库设置时才需要包含这些头文件。

所有类和函数都在命名空间 boost::flyweights 中。示例 66.2 仅使用类 boost::flyweights::flyweight,这是该库中最重要的类。成员变量 city_ 使用类型 flyweight<std::string> 而不是 std::string。这是您需要更改的所有内容,以使用此设计模式并减少程序的内存需求。

示例 66.3。多次使用 boost::flyweights::flyweight

#include <boost/flyweight.hpp>
#include <string>
#include <vector>
#include <utility>
using namespace boost::flyweights;
struct person
{
  int id_;
  flyweight<std::string> city_;
  flyweight<std::string> country_;
  person(int id, std::string city, std::string country)
    : id_{id}, city_{std::move(city)}, country_{std::move(country)} {}
};
int main()
{
  std::vector<person> persons;
  for (int i = 0; i < 100000; ++i)
    persons.push_back({i, "Berlin", "Germany"});
}

Example 66.3 

示例 66.3 向类 person 添加了第二个成员变量 country_。这个成员变量包含人们居住的国家的名字。因为在这个例子中,所有人都住在柏林,所以他们都住在同一个国家。这就是为什么在成员变量 country_ 的定义中也使用了 boost::flyweights::flyweight。

Boost.Flyweight 使用一个内部容器来存储对象。它确保不能有多个具有相同值的对象。默认情况下,Boost.Flyweight 使用哈希容器,例如 std::unordered_set。对于不同的类型,使用不同的散列容器。与示例 66.3 一样,成员变量 city_ 和 country_ 都是字符串;因此,只使用一个容器。在此示例中,这不是问题,因为容器仅存储两个字符串:“Berlin”和“Germany”。如果必须存储许多不同的城市和国家,最好将城市存储在一个容器中,将国家存储在另一个容器中。

示例 66.4。多次使用 boost::flyweights::flyweight 标签

#include <boost/flyweight.hpp>
#include <string>
#include <vector>
#include <utility>
using namespace boost::flyweights;
struct city {};
struct country {};
struct person
{
  int id_;
  flyweight<std::string, tag<city>> city_;
  flyweight<std::string, tag<country>> country_;
  person(int id, std::string city, std::string country)
    : id_{id}, city_{std::move(city)}, country_{std::move(country)} {}
};
int main()
{
  std::vector<person> persons;
  for (int i = 0; i < 100000; ++i)
    persons.push_back({i, "Berlin", "Germany"});
}

示例 66.4 将第二个模板参数传递给 boost::flyweights::flyweight。这是一个标签。标签是任意类型,仅用于区分 city_ 和 country_ 所基于的类型。示例 66.4 定义了两个空结构城市和国家,用作标签。但是,该示例可以改为使用 int、bool 或任何类型。

标签使 city_ 和 country_ 使用不同的类型。现在 Boost.Flyweight 使用了两个哈希容器——一个存储城市,另一个存储国家。

示例 66.5。 boost::flyweights::flyweight 的模板参数

#include <boost/flyweight.hpp>
#include <boost/flyweight/set_factory.hpp>
#include <boost/flyweight/no_locking.hpp>
#include <boost/flyweight/no_tracking.hpp>
#include <string>
#include <vector>
#include <utility>
using namespace boost::flyweights;
struct person
{
  int id_;
  flyweight<std::string, set_factory<>, no_locking, no_tracking> city_;
  person(int id, std::string city) : id_{id}, city_{std::move(city)} {}
};
int main()
{
  std::vector<person> persons;
  for (int i = 0; i < 100000; ++i)
  persons.push_back({i, "Berlin"});
}

标签以外的模板参数可以传递给 boost::flyweights::flyweight。示例 66.5 通过 boost::flyweights::set_factory、boost::flyweights::no_locking 和 boost::flyweights::no_tracking。包含额外的头文件以使用这些类。

boost::flyweights::set_factory 告诉 Boost.Flyweight 使用排序容器,例如 std::set,而不是散列容器。使用 boost::flyweights::no_locking,通常默认激活的对多线程的支持被停用。 boost::flyweights::no_tracking 告诉 Boost.Flyweight 不要跟踪存储在内部容器中的对象。默认情况下,当不再使用对象时,Boost.Flyweight 会检测到这一点并将它们从容器中移除。当设置了 boost::flyweights::no_tracking 时,检测机制被禁用。这提高了性能。但是,容器只能增长,永远不会收缩。

Boost.Flyweight 支持额外的设置。如果您对调整的更多细节感兴趣,请查看官方文档。

炼习

使用 Boost.Flyweight 改进这个程序。使用禁用多线程支持的 Boost.Flyweight:

#include <string>
#include <vector>
#include <memory>
int main()
{
    std::vector<std::shared_ptr<std::string>> countries;
    auto germany = std::make_shared<std::string>("Germany");
    for (int i = 0; i < 500; ++i)
        countries.push_back(germany);
    auto netherlands = std::make_shared<std::string>("Netherlands");
    for (int i = 0; i < 500; ++i)
        countries.push_back(netherlands);
}

到此这篇关于C++ Boost Flyweight库使用介绍的文章就介绍到这了,更多相关C++ Boost Flyweight内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++基于控制台实现的贪吃蛇小游戏

    C++基于控制台实现的贪吃蛇小游戏

    这篇文章主要介绍了C++基于控制台实现的贪吃蛇小游戏,实例分析了贪吃蛇游戏的原理与C++实现技巧,是非常经典的游戏算法,需要的朋友可以参考下
    2015-04-04
  • C++11特性小结之decltype、类内初始化、列表初始化返回值

    C++11特性小结之decltype、类内初始化、列表初始化返回值

    这篇文章主要介绍了C++11特性小结之decltype、类内初始化、列表初始化返回值,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • 使用OpenGL创建窗口的示例详解

    使用OpenGL创建窗口的示例详解

    OpenGL,也就是Open Graphics Library。其主要就是用于我们去渲染2D、3D矢量图形的一种跨语言、跨平台的应用程序编程接口,这篇文章主要介绍了使用OpenGL创建窗口,需要的朋友可以参考下
    2022-04-04
  • C++可变参数的实现方法

    C++可变参数的实现方法

    可变参数给编程带来了很大的方便,在享受它带来的方便的同时,很有必要了解一下其实现方式,在了解编程语言的同时,也可以扩展编程的思路。
    2013-03-03
  • C++类的返回值是*this的成员函数问题

    C++类的返回值是*this的成员函数问题

    这篇文章主要介绍了C++类的返回值是*this的成员函数问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • Qt的Qss用法小结

    Qt的Qss用法小结

    Qt的Qss是一种用于定义用户界面的样式表语言,本文主要介绍了Qt的Qss用法小结,非常具有实用价值,需要的朋友可以参考下
    2023-06-06
  • C语言关键字之auto register详解

    C语言关键字之auto register详解

    这篇文章主要为大家介绍了C语言关键字之auto register,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-01-01
  • C语言float内存布局示例详解

    C语言float内存布局示例详解

    这篇文章主要为大家介绍了C语言float内存布局示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • 利用C++实现最长公共子序列与最长公共子串

    利用C++实现最长公共子序列与最长公共子串

    这篇文章主要给大家介绍了如何利用C++实现最长公共子序列与最长公共子串,文章一开始就给大家简单的介绍了什么是子序列,子串应该比较好理解就不用多介绍了,人后通过算法及示例代码详细介绍了C++实现的方法,有需要的朋友们可以参考借鉴,下面来一起看看吧。
    2016-12-12
  • C++ 单链表的基本操作(详解)

    C++ 单链表的基本操作(详解)

    下面小编就为大家带来一篇C++ 单链表的基本操作(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12

最新评论