《STL源码剖析》学习笔记——空间配置

本文深入探讨了STL(标准模板库)的空间配置器机制,包括内存池的使用、对象构造与析构分离以及联合体的巧妙应用等内容,旨在提高程序员对STL内部运作的理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

相信大多数人应该和我一样,对STL的认识是从使用它开始的。但是,这等利器都是双刃剑,不明原理地使用,往往会适得其反。举个例子来说,对vector进行增添或者删除之后,出于内存安全的考虑,原有的迭代器应该摒弃不用。或许,只有真正走进STL的源码,才能解答这些疑问。 《STL源码剖析》这本书的源码来自大名鼎鼎的SGI STL,它是相对来说可读性最高的一个版本。

从实现的角度来看,空间配置器是一切的基础。当我们使用各种容器,进行各种操作时, 空间配置器总是默默地在我们看不见的地方做出自己的贡献。

SGI STL对内存的使用可以用两个词形容,可能不太准确:奢侈、精打细算。这一切都是为了:效率。下面是我的几点拙见。

1、内存池(memory pool)的概念

在STL二级空间配置中,内存池的使用可谓奢侈。若在第一次使用时,你想要一个8bytes区块,STL会要得40个这样的 8bytes区块,其中一个给你用,19个挂到free-list的一号桶下面,剩余20个会放到内存池中,以供将来使用。这样做的好处是,以后分配内存会直接从内存池中分配,提高了效率。

2、将内存分配和对象的构造/析构分开

template <class T1, class T2>
inline void construct (T1* p, const T2& value) {
    new (p) T1(value);
}

template <class T>
inline void destroy(T* pointer) {
    pointer->~T();
}
这里只列出了第一种destroy方法,第二中可以析构掉一批对象。

这里通过new占位符,来进行单纯的对象构造,只需要传入之前分配好的内存池中的地址,就可以在它之上构造出T1对象。destroy方法只负责析构对象,内存不会同时被释放掉。这样做的好处是:可以避免进行频繁的对象构造/析构时,内存也随之不停地获取和释放,从而提高了速度。

3、联合体的使用

在free-list中,使用了联合体来实现其中的节点:

union obj {
    union obj * free_list_link;
    char client_data[1];
}
这种结构既可以连接下一个节点,也可以为客端提供区块。这种“一物二用”的思想这是节省到家了!

联合体的另一个传神使用是:

struct in_addr{
    union {
        struct {u_char s_b1, s_b2, s_b3, s_b4;} S_un_b;
        struct {u_short s_w1, s_w2;} S_un_w;
        u_long S_addr;
    } S_un;
};
这种结构用被用于windows socket编程中,存储IP。这样做的好处不言而喻。


未完待续......



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值