侵入式容器及Boost.Intrusive

来源:互联网 发布:java简历项目经验实例 编辑:程序博客网 时间:2024/05/23 23:42

非侵入式容器和侵入式容器概念


非侵入式容器存储的是对象的拷贝,而不是传递给容器的原始对象,例如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操作,任何时刻可将自身从容器删除
3.void_pointer<class VoidPointer> hook内部使用的指针类型,默认是void指针, 可以定制,例如使用智能指针: list_base_hook<void_pointer<my_smart_ptr<void> >


侵入式容器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

0 0
原创粉丝点击