非侵入式容器和侵入式容器概念
非侵入式容器存储的是对象的拷贝,而不是传递给容器的原始对象,例如STL容器,当插入对象时,需要申请内存存放拷贝的对象,而对象在容器内的关系是由容器本身数据结构来维护的,内容内对象本事并不知道容器信息。
侵入式容器直接存储传递给容器的原始对象,而不是对象的拷贝。对象内部维护和容器之间的关系。
非侵入式容器的一些限制
1.一个对象同时只能存储在一个非侵入式容器。如果想同时存放到多个容器,需要在容器中保存对象的指针
2.非侵入式容器保存对象时,需要创建对象的拷贝,这在某些情况下会带来性能问题(C++11 STL emplace系列接口一定程度缓解了此问题)
3.非侵入式容器保存对象时需要申请内存,这会带来一定的开销
4.当非侵入式容器保存对象时,需要调用对象的拷贝或转移构造函数。没有提供拷贝或转移构造函数的对象无法存入侵入式对象
5.当非侵入式容器保存的是原始类型时,不能保存该对象的派生类
侵入式容器优点
1.侵入式容器接口操作不会引起任何的内存分配操作
2.侵入式容器侵入式容器的访问需要更小的内存操作,因此效率更高
3.侵入式容器有更好的安全性保证,部分能做到no-throw, 而非侵入式容器是无法做到的
4.侵入式容器中,由元素获得其在容器中的iterator是一个O(1)操作
5.侵入式容器的insert和erase操作不涉及内存的申请和释放,因此行为是确定的,而侵入式容器不是。
6.极致的性能,将非侵入式容器中时间复杂度为O(n)或O(lgn)操作直接变成了O(1)
侵入式容器的副作用
1.接入侵入式容器的对象必须在对象内部维护额外的数据,以供容器组织数据结构。这可以通过继承特定的基类,或定义特定类型的成员变量实现。
2.对象的生命周期独立与容器,这增加了生命周期管理的复杂度
3.通过对象自身的方法调用,可以将对象从容器删除,这很方便,也可能是容器的iterator失效。
4.侵入只容器不能copy和assignment, 因为容器没有对象的所有权,但是可以swap操作实现move语义
5.线程安全性不好保证,因为容器修改不依赖与容器本身的接口
Boost.Intrusvie
在C代码中,侵入式容器早已被广泛应用,特别是像内存管理算法,列表结构等。由于STL不提供侵入式容器,C++中使用倒不多。Boost.Intrusive是C++中侵入式容器类库,相比与STL容器,侵入式容器有更好的性能和异常安全保证Boost.Intrusvie侵入式容器采用模板技术实现,不需要依赖任何库文件。提供STL非侵入式容器相近接口,STL容器使用经验可以很方便应用到侵入式容器。
Hook
Hook封装容器所需要的数据,任何需要接入侵入式容器的类,要么派生自某个Hook, 成为Base hook, 要么定义Hook成员变量, 称为Member hook。若要接入多个侵入式容器,需要使用多个hook。
不同类型的容器对应不通的Hook.
下面以list hook说明
template <class ...Options>class list_base_hook;
支持的选项
1.tag<classTag> 标记, 对象可同时在不同的侵入式容器中,这是需要不通的tag值。可选
2.link_mode<link_mode_type LinkType> link策略,当前支持三种模式
- normal_link
- safe_link 默认使用该策略。构造时hook置为默认状态,析构时检查hook状态,如果不在默认状态,则assert(false)。insert操作时,检查hook状态,如果不在默认状态,则assert(false)。erase操作时hook置为默认状态
- auto_unlink hook 析构时,检查对象是否在容器中,如果在的话,自动从容器删除。实现unlink操作,任何时刻可将自身从容器删除
侵入式容器list
template <class T, class ...Options> class list;
list 容器支持以下选项、
1.base_hook<class Hook> / member_hook<class T, class Hook, class T:: PtrToMember> / value_traits<classValueTraits> 使用的hook类型,如果不指定,使用默认tag的hook
2.constant_time_size<boolEnabled> 指定size()函数是否需要在O(1)时间内完成,如果是的话,会在侵入式容器额外定义成员变量保存大小。默认为True
3.size_type<classSizeType> size()函数返回类型,通常使用默认值
使用示例
Baes Hook
struct my_tag1 {};
typedef list_base_hook<tag<my_tag> > BaseHook;
class Foo : public BaseHook {};
typedef list<Foo, base_hook<Basehook> > FooList;
Member Hook
class Foo { public: list_member_hook<> hook_; };
typedef member_hook<Foo, list_member_hook<> &Foo::hook_> MemberHookOption;
typedef list<Foo, MemberHookOption> FooList;
Boost实现的侵入式容器
1.slist
2.list
3.set/mutliset/rbtree
4.avl_set/avl_multiset/avltree
5.splay_set/splay_multiset/splaytree
6.sg_set/sg_multiset/sgtree