【BOOST C++ 20 设计模式】(1)库Boost.Flyweight
创始人
2024-03-16 10:32:52
0

一、说明

        以下库用于设计模式。

  • 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 
#include struct person
{int id_;std::string city_;
};int main()
{std::vector 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 
#include 
#include 
#include using namespace boost::flyweights;struct person
{int id_;flyweight city_;person(int id, std::string city) : id_{id}, city_{std::move(city)} {}
};int main()
{std::vector 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。这是您需要更改的所有内容,以使用此设计模式并减少程序的内存需求。

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

#include 
#include 
#include 
#include using namespace boost::flyweights;struct person
{int id_;flyweight city_;flyweight country_;person(int id, std::string city, std::string country): id_{id}, city_{std::move(city)}, country_{std::move(country)} {}
};int main()
{std::vector 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 
#include 
#include 
#include using namespace boost::flyweights;struct city {};
struct country {};struct person
{int id_;flyweight> city_;flyweight> country_;person(int id, std::string city, std::string country): id_{id}, city_{std::move(city)}, country_{std::move(country)} {}
};int main()
{std::vector 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 
#include 
#include 
#include 
#include 
#include 
#include using namespace boost::flyweights;struct person
{int id_;flyweight, no_locking, no_tracking> city_;person(int id, std::string city) : id_{id}, city_{std::move(city)} {}
};int main()
{std::vector 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 
#include 
#include int main()
{std::vector> countries;auto germany = std::make_shared("Germany");for (int i = 0; i < 500; ++i)countries.push_back(germany);auto netherlands = std::make_shared("Netherlands");for (int i = 0; i < 500; ++i)countries.push_back(netherlands);
}

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【Ctfer训练计划】——(三... 作者名:Demo不是emo  主页面链接:主页传送门 创作初心ÿ...