欢迎光临
我们一直在努力

Boost学习笔记2:内存管理

    内存管理一直是一件令人头疼的事,针对内存管理,Boost 提供了一套从底层对齐控制、内存池、智能指针到跨进程共享内存的完整工具链。下面按场景分类介绍。

一. 智能指针(Smart Pointers)

尽管 C++11 引入了 std::shared_ptr, std::weak_ptr, std::unique_ptr,但 Boost 仍有其独有价值,尤其是侵入式指针和本地共享指针。

库头文件核心类说明
Smart Ptr <boost/smart_ptr.hpp> shared_ptr, weak_ptr C++11 前的事实标准,现推荐使用标准库版本
scoped_ptr 类似 unique_ptr 但不可移动,已不建议使用
intrusive_ptr 侵入式引用计数,对象自己维护计数,更轻量
local_shared_ptr 结合本地存储和共享所有权的指针,避免 shared_ptr 的线程安全开销
make_shared / allocate_shared 与标准一致

scoped_ptr 

scoped_ptr 是 Boost 智能指针库中的一个老组件,用于独占资源所有权,并在指针离开作用域时自动 delete 释放对象。

基本特征

  • 独占所有权:一个对象同一时间只能被一个 scoped_ptr 管理。

  • 不可拷贝、不可转移:拷贝构造和赋值操作都是私有的,无法传递所有权。对象严格限定在声明它的作用域内。

  • 轻量级:没有引用计数,没有控制块,比 shared_ptr 更轻。

  • 异常安全:确保资源在异常发生时也能被正确释放。

intrusive_ptr

boost::intrusive_ptr 是 Boost 智能指针家族中最轻量、最高效的引用计数智能指针。它与 boost::shared_ptr 或 std::shared_ptr 最大的区别是:引用计数器存储在对象内部,而不是分配在独立的控制块上。

为什么叫“侵入式” (Intrusive)?因为对象本身必须提供两个函数接口来维护引用计数:

  • intrusive_ptr_add_ref(T*) —— 增加引用计数

  • intrusive_ptr_release(T*) —— 减少引用计数,当计数归零时负责销毁对象

这两个函数由你定义(通常在对象所在命名空间或作为友元),Boost 会在构造/拷贝/析构 intrusive_ptr 时自动调用它们。

2. 和 shared_ptr 的核心区别

特性shared_ptr / std::shared_ptrintrusive_ptr
引用计数位置 堆上独立控制块(每次构造 shared_ptr 都会分配) 对象内部(通常是一个整型成员)
内存开销 两次分配:一次对象,一次控制块 仅分配对象本身(计数内嵌)
性能 控制块分配、原子操作(线程安全) 零额外分配;是否原子操作由你决定(可非线程安全)
构造方式 shared_ptr<T> p(new T); 或 make_shared intrusive_ptr<T> p(new T); 但对象必须已实现计数接口
对象类型要求 任意类型 对象必须支持侵入式引用计数(即拥有 add_ref / release 机制)
与裸指针互操作 不能直接从已有裸指针安全创建另一个 shared_ptr 可从已有裸指针安全构造多个 intrusive_ptr(因为计数在对象内)
适用场景 通用引用计数,简单易用 与现有引用计数系统(如 COM、内部框架)无缝集成;极致性能要求

#include <boost/smart_ptr/intrusive_ptr.hpp>

//定义侵入式计数函数
class MyObject {
private:
unsigned int ref_count_ = 0; // 引用计数
public:
// 允许 intrusive_ptr 操作计数
friend void intrusive_ptr_add_ref(MyObject* p) {
++p->ref_count_;
}
friend void intrusive_ptr_release(MyObject* p) {
if (–p->ref_count_ == 0)
delete p;
}

virtual ~MyObject() = default; // 注意:最好为多态基类,否则 delete 需要正确调用析构
void do_something() { /* … */ }
};

//直接使用 intrusive_ptr
boost::intrusive_ptr<MyObject> p1(new MyObject); // ref_count_ 变为 1
boost::intrusive_ptr<MyObject> p2 = p1; // ref_count_ 变为 2
p1.reset(); // ref_count_ 减为 1
// 当 p2 离开作用域,ref_count_ 归零,自动 delete

二. 内存池(Boost.Pool)

Boost.Pool 是专门设计用于快速分配大量固定大小的小对象的库,可有效减少内存碎片和 malloc 调用开销。

头文件主要组件用途
<boost/pool/pool.hpp> boost::pool 最基本的无类型内存池,一次分配固定大小的内存块
<boost/pool/object_pool.hpp> boost::object_pool<T> 类型安全的对象池,自动调用构造/析构
<boost/pool/singleton_pool.hpp> boost::singleton_pool 带单例优化的线程安全内存池
<boost/pool/pool_alloc.hpp> pool_allocator 可作为 STL 容器(如 std::list)的分配器

#include <boost/pool/object_pool.hpp>
struct Point { int x, y; };

boost::object_pool<Point> pool;
Point* p1 = pool.construct(); // 分配并构造(如无参,则使用默认构造)
p1->x = 10; p1->y = 20;

Point* p2 = pool.malloc(); // 仅分配内存,不构造
new (p2) Point{30, 40}; // placement new

pool.destroy(p1); // 调用析构并释放回池
pool.free(p2); // 仅释放内存(不调用析构)
// pool 析构时会自动释放所有未还回的内存(但不会调用析构,注意泄漏)

注意:object_pool::destroy() 会调用析构函数并释放内存;而 free() 不调用析构。如果对象生命周期管理不当,会造成资源泄漏。

编译依赖:Boost.Pool 需要编译和链接(-lboost_pool)。

三. 内存对齐(Boost.Align)

C++11 有 alignas,但 Boost.Align 提供更灵活的运行时对齐分配函数和分配器。

头文件功能
<boost/align/aligned_alloc.hpp> aligned_alloc(alignment, size) 运行时对齐分配
<boost/align/aligned_delete.hpp> aligned_delete 专门用于对齐内存的删除器
<boost/align/aligned_allocator.hpp> aligned_allocator<T, Alignment> 可作为容器分配器

示例:

#include <boost/align/aligned_alloc.hpp>
#include <boost/align/aligned_allocator.hpp>
#include <vector>

// 分配 16 字节对齐的内存
void* p = boost::alignment::aligned_alloc(16, 1024);
boost::alignment::aligned_free(p); // 必须用对应的释放

// 用于 std::vector,所有元素 16 字节对齐
std::vector<int, boost::alignment::aligned_allocator<int, 16>> v;

四. 容器分配器与作用域分配器(Boost.Container)

Boost.Container 不仅提供了更丰富的容器(如 flat_map, stable_vector),还提供了分配器工具,用于复杂的嵌套容器内存管理。

  • <boost/container/scoped_allocator.hpp> 实现 scoped_allocator_adaptor,允许容器的元素(本身也是容器)使用同一个分配器。

  • 适合在共享内存等场景下,所有子对象都从同一内存区域分配。

#include <boost/container/scoped_allocator.hpp>
#include <boost/container/list.hpp>
#include <boost/container/vector.hpp>
#include <boost/pool/pool_alloc.hpp>

using Alloc = boost::pool_allocator<int>;
using MyList = boost::container::list<int, Alloc>;
using MyVec = boost::container::vector<MyList, boost::container::scoped_allocator_adaptor<Alloc>>;

Alloc alloc;
MyVec vec(alloc); // 向量及其内部的链表都使用同一个 pool_allocator
vec.emplace_back(); // 内部 list 自动继承分配器

五. 共享内存(Boost.Interprocess)

如果“内存管理”指的是跨进程共享内存,则需要 Boost.Interprocess。它提供:

  • shared_memory_object / mapped_region 创建/映射共享内存

  • managed_shared_memory 可在共享内存上直接构造对象

  • 特殊分配器(allocator),让 STL 容器放在共享内存里

  • 同步原语(互斥锁、条件变量)用于进程间同步


六. 其他相关

  • Boost.Smart_Ptr 的 make_unique 等在 C++11 后基本被标准取代,但维护旧代码时会碰到。

  • Boost.Any、Boost.Variant 内部也涉及动态内存分配,但不属于专门的内存管理库。

  • Boost.Circular_Buffer 使用连续内存,可避免频繁分配。

如何选择?

场景推荐方案
大量小对象频繁分配/释放 boost::object_pool
需要对齐分配(SIMD、DMA) boost::alignment::aligned_alloc
侵入式引用计数,避免多控块开销 boost::intrusive_ptr
STL 容器定制内存来源(如共享内存) pool_allocator 或自定义分配器
多进程通信与内存共享 Boost.Interprocess
赞(0)
未经允许不得转载:171主机测评 » Boost学习笔记2:内存管理
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址