C++ Boost Flyweight库使用介绍

目录
  • 一、说明
  • 二、库Boost.Flyweight
  • 炼习

一、说明

以下库用于设计模式。

  • 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内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++ Boost Uuid超详细讲解

    目录 一.说明 二.Boost.Uuid库示例和代码 一.说明 Boost.Uuid 为 UUID 提供生成器. UUID 是不依赖于中央协调实例的通用唯一标识符.例如,没有数据库存储所有生成的 UUID,可以检查这些 UUID 是否使用了新的 UUID. UUID 由必须唯一标识组件的分布式系统使用.例如,Microsoft 使用 UUID 来识别 COM 世界中的接口.对于为 COM 开发的新接口,可以轻松分配唯一标识符. UUID 是 128 位数字.存在多种生成 UUID 的方法.例如,

  • C++ Boost MetaStateMachine定义状态机超详细讲解

    目录 一.说明 二.示例和代码 一.说明 Boost.MetaStateMachine 用于定义状态机.状态机通过对象的状态来描述对象.它们描述了存在哪些状态以及状态之间可能存在哪些转换. Boost.MetaStateMachine 提供了三种不同的方式来定义状态机.创建状态机所需编写的代码取决于前端. 如果使用基本前端或函数前端,则可以用常规方式定义状态机:创建类,从 Boost.MetaStateMachine 提供的其他类派生它们,定义所需的成员变量,并编写所需的 C++自己编码.基本前

  • C++ Boost Assign超详细讲解

    目录 说明 Exercise 说明 Boost.Assign Boost.Assign 库提供了帮助函数来初始化容器或向容器添加元素.如果需要将许多元素存储在一个容器中,这些函数尤其有用.多亏了 Boost.Assign 提供的函数,您不需要重复调​​用像 push_back() 这样的成员函数来将元素一个一个地插入到容器中. 如果您使用支持 C++11 的开发环境,则可以从初始化列表中获益.通常您可以将任意数量的值传递给构造函数来初始化容器.多亏了初始化列表,你不必依赖 C++11 的 Boo

  • C++ Boost ProgramOptions超详细讲解

    目录 一.说明 二.示例Boost.ProgramOptions 一.说明 Boost.ProgramOptions Boost.ProgramOptions 是一个可以轻松解析命令行选项的库,例如,控制台应用程序.如果您使用图形用户界面开发应用程序,命令行选项通常并不重要. 要使用 Boost.ProgramOptions 解析命令行选项,需要以下三个步骤: 定义命令行选项.您给它们命名并指定哪些可以设置为一个值.如果命令行选项被解析为键/值对,您还可以设置值的类型——例如,它是字符串还是数字

  • C++ Boost.Signals2信号/槽概念

    目录 一.关于Boost.Signals2 二.关于Signals库 练习 一.关于Boost.Signals2 Boost.Signals2 实现了信号/槽的概念.一个或多个函数(称为槽)与可以发出信号的对象相关联.每次发出信号时,都会调用链接的函数. 信号/槽概念在开发具有图形用户界面的应用程序时非常有用.可以对按钮进行建模,以便在用户单击它们时发出信号.它们可以支持指向许多函数的链接以处理用户输入.这样就可以灵活地处理事件. std::function 也可用于事件处理. std::fun

  • C++ Boost Utility超详细讲解

    目录 一.说明 二.Boost.Utility库示例和代码 一.说明 Boost.Utility 库是杂项.有用的类和函数的集合,它们太小而无法在独立库中维护.虽然实用程序很小并且可以快速学习,但它们完全无关.与其他章节中的示例不同,此处的代码示例不是相互构建的,因为它们是独立的实用程序. 虽然大多数实用程序都在 boost/utility.hpp 中定义,但有些实用程序有自己的头文件.以下示例包括所介绍的实用程序的相应头文件. 二.Boost.Utility库示例和代码 示例 69.1.使用

  • C++ Boost Archive超详细讲解

    目录 一.说明 二.关于Archive库 一.说明 对Boost.Serialization库的应用,存在如下内容: Archive Pointers and References Serialization of Class Hierarchy Objects Wrapper Functions for Optimization Boost.Serialization 库可以将 C++ 程序中的对象转换为可以保存和加载以恢复对象的字节序列.有不同的数据格式可用于定义生成字节序列的规则. Boo

  • C++ Boost Flyweight库使用介绍

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

  • C++中的boost::function库简介

    boost::function Boost.Function库用来提供一个对象化的函数指针,通过它可以很容易的将一个函数封装为仿函数. boost::function库可以支持自由函数,函数对象,类成员函数.而且参数个数多达10个.boost::function库利用模板技术来实现.生成的代码有很高的运行效率.首先我们还是以一个例子简单的说明它的用法: #include <iostream> #include <boost/function.hpp> using namespace

  • C++ Boost Intrusive库示例精讲

    目录 一.说明 二.示例 一.说明 Boost.Intrusive 是一个特别适合在高性能程序中使用的库.该库提供了创建侵入式容器的工具.这些容器替换了标准库中的已知容器.它们的缺点是它们不能像 std::list 或 std::set 那样容易使用.但它们有以下优点: 侵入式容器不会动态分配内存.对 push_back() 的调用不会导致使用 new 进行动态分配.这是侵入式容器可以提高性能的一个原因. 侵入式容器不会动态分配内存.对 push_bacIntrusive 容器的调用存储原始对象

  • C++ Boost EnableIf函数使用介绍

    目录 一.说明 二.Boost.EnableIf的示例 练习 一.说明 Boost.EnableIf Boost.Enable If 可以禁用重载函数模板或专用类模板.禁用意味着编译器忽略相应的模板.这有助于防止出现模棱两可的情况,即编译器不知道要使用哪个重载函数模板.它还可以更轻松地定义不仅可用于特定类型而且可用于一组类型的模板. 从 C++11 开始,Boost.EnableIf 已经成为标准库的一部分.您可以在不使用 Boost 库的情况下调用本章介绍的函数:只需包含头文件 type_tr

  • C++ boost thread库用法详细讲解

    目录 一.说明 二.boost::thread的几个函数 三.构造 一.说明 boost::thread的六种使用方法总结,本文初步介绍线程的函数.构造.执行的详细解释. 二.boost::thread的几个函数 函数 功能 join() 让主进程等待子线程执行完毕后再继续执行 get_id() 获得线程的 id 号 detach() 标线程就成为了守护线程,驻留后台运行 bool joinable() 是否已经启动,为 join() thread::join()是个简单暴力的方法,主线程等待子

  • C++ Boost Phoenix库示例分析使用

    目录 一.说明 二.预先知道Boost.Phoenix 三.示例和代码 一.说明 在函数式编程模型中,函数是对象,与其他对象一样,可以作为参数传递给函数或存储在容器中.有许多支持函数式编程模型的 Boost 库. Boost.Phoenix 是这些库中最广泛.也是最重要的库.它取代了库 Boost.Lambda,它被简要介绍,但只是为了完整性. Boost.Function 提供了一个类,可以轻松定义函数指针,而无需使用源自 C 编程语言的语法. Boost.Bind 是一个适配器,即使实际签名

  • C++ Boost TypeTraits库使用详解

    目录 一.说明 二.库Boost.TypeTraits 一.说明 反省是重点中的重点,泛型在实践中贯穿工程的始终.以下库支持泛型编程.无需详细了解模板元编程即可使用这些库. Boost.TypeTraits 提供了检查类型属性的函数. Boost.EnableIf 可以与 Boost.TypeTraits 一起使用,例如,根据函数的返回类型重载函数. Boost.Fusion 使创建异构容器成为可能——其元素可以具有不同类型的容器. Boost.TypeTraits Boost.EnableIf

  • IOS 打包静态库详细介绍

    IOS 打包静态库详细介绍 一.前言 前段时间看的一本书上说:"隔着一段距离看,很多有趣的知识看起来都很唬人."比如说这篇我要总结的"静态库知识",在我初出茅庐的时候着实觉得那些后缀名为".frameworke".".a".".dylib"的文件很神秘,很高冷.那时我虽然知道只要导入一个库就能引用库里面很多封装好的东西,但对这个"库"究竟是什么"鬼",一直都是云里雾里

  • VS2010 boost标准库开发环境安装教程

    分享VS2010 boost标准库开发环境安装教程 1. BOOST编译过程非常复杂,目前为了学习BOOST,首先搭建基于VS2010的BOOST开发环境. Boost库是一个可移植.提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一.Boost库由C++标准委员会库工作组成员发起,其中有些内容有望成为下一代C++标准库内容.在C++社区中影响甚大,是不折不扣的"准"标准库.Boost由于其对跨平台的强调,对标准C++的强调,与编写平台无关.大部分boost库功能

  • 聊聊python的gin库的介绍和使用

    1.简介 由于现在很多机器学习的实验需要设置繁琐的参数,在多次实验中,有些参数是一样的,为了方便设置参数,Gin库出现了.它允许函数或类被注释为@gin.configurable,这使得能够使用清晰而强大的语法通过简单的配置文件来设置它们的参数.这种方法减少了配置维护,同时使实验配置透明且易于重复. 简单理解,gin像一个封装了参数配置的类,使用这个类将使得大量的参数配置变得简单清晰 安装 pip install gin-config 2.@gin.configurable 任何函数和类都可以使

随机推荐