我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C++BoostIntrusive库示例精讲

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C++BoostIntrusive库示例精讲

一、说明

Boost.Intrusive 是一个特别适合在高性能程序中使用的库。该库提供了创建侵入式容器的工具。这些容器替换了标准库中的已知容器。它们的缺点是它们不能像 std::list 或 std::set 那样容易使用。但它们有以下优点:

  • 侵入式容器不会动态分配内存。对 push_back() 的调用不会导致使用 new 进行动态分配。这是侵入式容器可以提高性能的一个原因。
  • 侵入式容器不会动态分配内存。对 push_bacIntrusive 容器的调用存储原始对象,而不是副本。毕竟,它们不会动态分配内存。这带来了另一个优势:诸如 push_back() 之类的成员函数不会抛出异常,因为它们既不分配内存也不复制对象。k() 不会导致使用 new 进行动态分配。这是侵入式容器可以提高性能的一个原因。

这些优势通过更复杂的代码得到了回报,因为必须满足先决条件才能将对象存储在侵入式容器中。您不能将任意类型的对象存储在侵入式容器中。例如,您不能将 std::string 类型的字符串放入侵入式容器中;相反,您必须使用标准库中的容器。

二、示例

示例 18.1 准备了一个类动物,以允许将此类对象存储在侵入式列表中。

示例 18.1。使用 boost::intrusive::list

#include <boost/intrusive/list.hpp>
#include <string>
#include <utility>
#include <iostream>
using namespace boost::intrusive;
struct animal : public list_base_hook<>
{
  std::string name;
  int legs;
  animal(std::string n, int l) : name{std::move(n)}, legs{l} {}
};
int main()
{
  animal a1{"cat", 4};
  animal a2{"shark", 0};
  animal a3{"spider", 8};
  typedef list<animal> animal_list;
  animal_list animals;
  animals.push_back(a1);
  animals.push_back(a2);
  animals.push_back(a3);
  a1.name = "dog";
  for (const animal &a : animals)
    std::cout << a.name << '\n';
}

在列表中,总是从另一个元素访问一个元素,通常使用指针。如果侵入式列表要在没有动态内存分配的情况下存储动物类型的对象,则指针必须存在于某处以连接元素。

要将动物类型的对象存储在侵入式列表中,该类必须提供侵入式列表所需的变量以连接元素。 Boost.Intrusive 提供了钩子——从这些类中继承了所需的变量。要允许将动物类型的对象存储在侵入列表中,动物必须从类 boost::intrusive::list_base_hook 派生。

钩子可以忽略实现细节。但是,可以安全地假设 boost::intrusive::list_base_hook 至少提供了两个指针,因为 boost::intrusive::list 是一个双向链表。多亏了基类 boost::intrusive::list_base_hook,animal 定义了这两个指针以允许连接这种类型的对象。

请注意 boost::intrusive::list_base_hook 是一个带有默认模板参数的模板。因此,不需要显式传递任何类型。

Boost.Intrusive 提供类 boost::intrusive::list 来创建一个侵入式列表。此类在 boost/intrusive/list.hpp 中定义,并像 std::list 一样使用。可以使用 push_back() 添加元素,也可以迭代元素。

重要的是要了解侵入式容器不存储副本;他们存储原始对象。示例 18.1 将狗、鲨鱼和蜘蛛写入标准输出,而不是猫。对象 a1 链接到列表中。这就是为什么当程序遍历列表中的元素并显示名称时名称的更改是可见的。

因为侵入式容器不存储副本,所以必须在销毁它们之前从侵入式容器中移除对象。

示例 18.2。删除和销毁动态分配的对象

#include <boost/intrusive/list.hpp>
#include <string>
#include <utility>
#include <iostream>
using namespace boost::intrusive;
struct animal : public list_base_hook<>
{
  std::string name;
  int legs;
  animal(std::string n, int l) : name{std::move(n)}, legs{l} {}
};
int main()
{
  animal a1{"cat", 4};
  animal a2{"shark", 0};
  animal *a3 = new animal{"spider", 8};
  typedef list<animal> animal_list;
  animal_list animals;
  animals.push_back(a1);
  animals.push_back(a2);
  animals.push_back(*a3);
  animals.pop_back();
  delete a3;
  for (const animal &a : animals)
    std::cout << a.name << '\n';
}

Example18.2

example18.2 使用 new 创建一个动物类型的对象并将其插入到动物列表中。如果您想在不再需要时使用 delete 来销毁该对象,则必须将其从列表中删除。确保在销毁之前从列表中删除该对象——顺序很重要。否则,侵入式容器元素中的指针可能会引用不再包含动物类型对象的内存位置。

因为侵入式容器既不分配也不释放内存,所以当侵入式容器被破坏时,存储在侵入式容器中的对象继续存在。

由于从侵入式容器中删除元素不会自动破坏它们,因此容器提供了非标准扩展。 pop_back_and_dispose() 就是这样的成员函数之一。

示例 18.3。使用 pop_back_and_dispose() 删除和销毁

#include <boost/intrusive/list.hpp>
#include <string>
#include <utility>
#include <iostream>
using namespace boost::intrusive;
struct animal : public list_base_hook<>
{
  std::string name;
  int legs;
  animal(std::string n, int l) : name{std::move(n)}, legs{l} {}
};
int main()
{
  animal a1{"cat", 4};
  animal a2{"shark", 0};
  animal *a3 = new animal{"spider", 8};
  typedef list<animal> animal_list;
  animal_list animals;
  animals.push_back(a1);
  animals.push_back(a2);
  animals.push_back(*a3);
  animals.pop_back_and_dispose([](animal *a){ delete a; });
  for (const animal &a : animals)
    std::cout << a.name << '\n';
}

pop_back_and_dispose() 从列表中删除一个元素并销毁它。因为侵入式容器不知道应该如何销毁元素,所以您需要向 pop_back_and_dispose() 传递一个知道如何销毁元素的函数或函数对象。 pop_back_and_dispose() 将从列表中删除对象,然后调用函数或函数对象并将指向要销毁的对象的指针传递给它。示例 18.3 传递了一个调用 delete 的 lambda 函数。

在示例 18.3 中,只有动物中的第三个元素可以使用 pop_back_and_dispose() 删除。列表中的其他元素尚未使用 new 创建,因此不得使用 delete 销毁。

Boost.Intrusive 支持另一种机制来链接元素的删除和销毁。

示例 18.4。使用自动取消链接模式删除和销毁

#include <boost/intrusive/list.hpp>
#include <string>
#include <utility>
#include <iostream>
using namespace boost::intrusive;
typedef link_mode<auto_unlink> mode;
struct animal : public list_base_hook<mode>
{
  std::string name;
  int legs;
  animal(std::string n, int l) : name{std::move(n)}, legs{l} {}
};
int main()
{
  animal a1{"cat", 4};
  animal a2{"shark", 0};
  animal *a3 = new animal{"spider", 8};
  typedef constant_time_size<false> constant_time_size;
  typedef list<animal, constant_time_size> animal_list;
  animal_list animals;
  animals.push_back(a1);
  animals.push_back(a2);
  animals.push_back(*a3);
  delete a3;
  for (const animal &a : animals)
    std::cout << a.name << '\n';
}

Hooks 支持一个参数来设置链接模式。链接模式使用类模板 boost::intrusive::link_mode 设置。如果 boost::intrusive::auto_unlink 作为模板参数传递,则选择自动取消链接模式。

自动取消链接模式会在破坏容器时自动从侵入式容器中删除元素。示例 18.4 仅将 cat 和 Shark 写入标准输出。

仅当所有侵入式容器提供的成员函数 size() 没有恒定的复杂性时,才能使用自动取消链接模式。默认情况下,它具有恒定的复杂性,这意味着:size() 返回元素数量所花费的时间不取决于容器中存储了多少元素。打开或关闭恒定复杂性是优化性能的另一种选择。

要更改 size() 的复杂性,请使用类模板 boost::intrusive::constant_time_size,它需要 true 或 false 作为模板参数。 boost::intrusive::constant_time_size 可以作为第二个模板参数传递给侵入式容器,例如 boost::intrusive::list,以设置 size() 的复杂度。

现在我们已经看到侵入式容器支持链接模式,并且可以选择设置 size() 的复杂度,看起来似乎还有很多东西需要发现,但实际上并没有。例如,仅支持三种链接模式,而自动取消链接模式是您唯一需要了解的一种。如果您不选择链接模式,则使用的默认模式足以满足所有其他用例。

此外,没有其他成员函数的选项。除了 boost::intrusive::constant_time_size 之外,没有其他类是您需要了解的。

示例 18.5 引入了使用另一个侵入式容器的挂钩机制:boost::intrusive::set。

示例 18.5。将 boost::intrusive::set 的钩子定义为成员变量

#include <boost/intrusive/set.hpp>
#include <string>
#include <utility>
#include <iostream>
using namespace boost::intrusive;
struct animal
{
  std::string name;
  int legs;
  set_member_hook<> set_hook;
  animal(std::string n, int l) : name{std::move(n)}, legs{l} {}
  bool operator<(const animal &a) const { return legs < a.legs; }
};
int main()
{
  animal a1{"cat", 4};
  animal a2{"shark", 0};
  animal a3{"spider", 8};
  typedef member_hook<animal, set_member_hook<>, &animal::set_hook> hook;
  typedef set<animal, hook> animal_set;
  animal_set animals;
  animals.insert(a1);
  animals.insert(a2);
  animals.insert(a3);
  for (const animal &a : animals)
    std::cout << a.name << '\n';
}

有两种方法可以将钩子添加到类:从钩子派生类或将钩子定义为成员变量。虽然前面的示例从 boost::intrusive::list_base_hook 派生了一个类,但示例 18.5 使用类 boost::intrusive::set_member_hook 来定义一个成员变量。

请注意,成员变量的名称无关紧要。但是,您使用的钩子类取决于侵入式容器。例如,要将挂钩定义为侵入式列表的成员变量,请使用 boost::intrusive::list_member_hook 而不是 boost::intrusive::set_member_hook。

侵入式容器有不同的钩子,因为它们对元素有不同的要求。但是,您可以使用不同的几个挂钩来允许将对象存储在多个侵入式容器中。 boost::intrusive::any_base_hook 和 boost::intrusive::any_member_hook 让您可以将对象存储在任何侵入式容器中。多亏了这些类,您不需要从多个钩子派生或将多个成员变量定义为钩子。

默认情况下,侵入式容器期望在基类中定义挂钩。如果将成员变量用作挂钩(如示例 18.5),则必须告知侵入式容器使用哪个成员变量。这就是为什么动物和类型挂钩都被传递给 boost::intrusive::set 的原因。 hook 使用 boost::intrusive::member_hook 定义,每当成员变量用作 hook 时都会使用它。 boost::intrusive::member_hook 期望元素类型、钩子类型和指向成员变量的指针作为模板参数。

示例 18.5 按此顺序将鲨鱼、猫和蜘蛛写入标准输出。

除了本章介绍的类 boost::intrusive::list 和 boost::intrusive::set 之外,Boost.Intrusive 还提供了例如单链表的 boost::intrusive::slist 和 boost::intrusive ::unordered_set 用于哈希容器。

到此这篇关于C++ Boost Intrusive库示例精讲的文章就介绍到这了,更多相关C++ Boost Intrusive内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C++BoostIntrusive库示例精讲

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C++BoostIntrusive库示例精讲

Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
2022-11-13

C++BoostContainer库示例详细讲解

Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
2022-11-13

C++BoostBimap示例详细讲解

Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
2022-11-13

Vue处理循环数据流程示例精讲

这篇文章主要介绍了Vue处理循环数据流程,这个又是一个编程语言, 模版语法里面必不可少的一个, 也是使用业务场景使用最多的一个环节。所以学会使用循环也是重中之重了
2023-05-15

C++BoostPropertyTree示例超详细讲解

Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
2022-11-13

C++BoostVariant示例超详细讲解

Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
2022-11-13

C++BoostOptional示例超详细讲解

Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
2022-11-13

C语言模拟实现字符串库函数的示例讲解

这篇文章主要为大家详细介绍了C语言模拟实现字符串库函数的具体方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2023-01-13

C++Futures与Promises线程使用示例讲解

future和promise的作用是在不同线程之间传递数据。使用指针也可以完成数据的传递,但是指针非常危险,因为互斥量不能阻止指针的访问;而且指针的方式传递的数据是固定的,如果更改数据类型,那么还需要更改有关的接口,比较麻烦
2022-11-21

C++示例讲解观察者设计模式

观察者模式是极其重要的一个设计模式,也是我几年开发过程中使用最多的设计模式,本文首先概述观察者模式的基本概念和Demo实现,接着是观察者模式在C++中的应用,最后是对观察者模式的应用场景和优缺点进行总结
2022-12-26

C++实现移动立方体示例讲解

这篇文章主要介绍了C++实现移动立方体,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
2022-12-21

MySQL数据库约束操作示例讲解

目录一、约束是什么二、约束的具体操作Not NULLUNIQUE约束的组合使用PRIMARY KEYDEFAULTFOREIGN KEY一、约束是什么约束就是,在创建表的时候,对表设置一些规则,只有满足这些规则,才可以插入数据,我们把这些
2022-11-15

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录