没有模板代码膨胀的STL:一、设计目标与实现思路

本文介绍了POD_STL项目,旨在解决C++中STL容器引起的模板代码膨胀问题。该项目实现了多种STL容器,如vector、map等,通过去模板化减少目标代码膨胀,同时不依赖C++运行时库,只使用C语言运行时库。此外,POD_STL使用统一内存管理接口,并保持与标准STL接口一致,允许在不修改代码的情况下替换现有STL。文章还详细阐述了实现思路和限制,以及与标准STL的裁剪功能对比。
摘要由CSDN通过智能技术生成

总目录
一、设计目标与实现思路
二、使用方法与注意事项
三、开发者指南
四、一些讨论和个人心得

公司里很多项目因为模板代码膨胀的问题而放弃甚至禁止使用STL。但是,STL又确实可以给编码带来诸多便利。
在此背景下,我发起了这个开源项目:POD_STL。当前已经完成了vector、string、list、deque、set、multiset、map、multimap等容器,以及一些基本算法、迭代器、函数对象、类型traits、pair的实现,可以支持大多数项目的使用需求。

设计目标

1、在不过多降低性能的前提下,尽量减小STL容器模板带来的目标代码膨胀。
什么是模板代码膨胀?在C++中,函数模板代表一类函数。使用非内联的函数模板时,对于每一种模板参数类型,编译器都会自动生成一个对应此类型实例化的函数。如果不同的实例化类型太多,就会造成目标文件中生成了大量对不同类型实例化的函数实体。这些函数的逻辑、算法几乎完全一样,只是操作的类型不同。这导致目标二进制文件变得太大。
类模板和函数模板类似,但其代码膨胀问题只出现在成员函数的实例化过程中。因为类定义本身不占用程序二进制空间。

POD_STL对于模板代码膨胀做的优化仅针对STL容器(比如vectormap等),不针对STL算法(如copyfind)。因为当前各个项目遇到的模板代码膨胀问题主要来自于容器。而STL算法大部分都是内联的,没有函数实体膨胀问题。

2、不依赖任何C++运行时库,只需要C语言运行时库就可以工作。
这是因为很多嵌入式项目并不需要使用异常等C++特性,如果链接C++运行时库会增大目标文件体积。POD_STL可以让项目只链接C语言运行时库,但仍然支持用C++语言编码,并且使用STL!

3、内部完全不使用new和delete关键字,只用统一的可定制接口(STL_MallocSTL_Free)来申请/释放内存。
这是为那些重载了newdelete操作符的项目考虑的。这些项目往往有自己的内存申请释放函数,他们可以通过定制POD_STL中的
STL_Malloc/STL_Free函数实现来方便的应用自己的内存操作。这样可以避免new/delete关键字被重载后带来的编译错误。
但是,完全不用new会导致一些STL算法无法实现(比如uninitialized_copy只能用new()实现)。这些算法在POD_STL中被裁减。好在这些算法一般用得很少。

4、所有接口与最新的STL标准保持一致。
当今已经有一些项目组自己实现了一些容器来替代STL。但是,还没有任何一套容器的使用方法与STL标准一致。这些替代容器对使用者提出很多要求,比如只允许存放void*指针,只允许map的索引为long long类型等等。这导致这些替代容器远远没有标准STL容器好用。而且一旦项目要从标准STL切换成自定义容器,就要投入很多人力进行整改。即使整改成功了,也把项目所有代码的可移植性大大降低了——毕竟STL接口是世界统一标准,但替代容器接口却是项目组自己闭门造车搞出来的。

POD_STL的所有对外接口与标准STL完全相同(极少数被裁剪的特性除外)!它仍然有完备的模板参数支持,有各种迭代器、算法、函数对象,仍然支持用自定义类型和自定义比较运算符来定制关系型容器(这意味着你可以用任何类型作为mapkey)。对于大多数项目,可以不需要修改任何代码,就直接切换到POD_STL,解决目标文件过大的问题!

当然,为了解决模板代码膨胀问题,POD_STL使用了一些优化技巧,其代价是部分STL的定制功能(比如allocator)被裁减,同时对于容器可以存放的元素类型也有限制。好在这些边缘功能平时用得很少,带来的影响并不大。

实现思路

要解决模板代码膨胀问题,最有效的方法是把内部函数实现去模板化。但是,由于容器外部接口不能改变,因此POD_STL的所有容器仍然是模板。但模板的所有成员函数都只是一个内联的“壳”,它仅仅只调用其非模板基类的另一个成员函数,在后者中实现真正的功能。

比如,vector容器的push_back函数是这样实现的:

01 class _VectorBase
02 {
03 protected:
04     void _M_push_back(const void* __data, size_t __unit_size);
05 };
06  
07 template <class _Tp>
08 class vector : public _VectorBase
09 {
10 public:
11     void push_back(const _Tp& __element = _Tp())
12     {
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值