软讯网络 > 编程语言 > C/C++ > Modern CPP--smart pointer2
【标 题】:Modern CPP--smart pointer2
【关键字】:
Modern,CPP--smart,pointer2
【来 源】:http://www.cublog.cn/u/1421/showart.php?id=230550
Modern CPP--smart pointer2
From <Modern Cpp>
本文介绍smart pointer的ownership处理策略。
1. Deep Copy
copy的时候,为新的smart pointer复制一份原有对象。这样,sp的dtor可以安全的delete。看似与对象直接传值无甚区别,但实际上可以支持多态。当然还需要一些辅助工作:典型的方法是在对象中声明虚拟的clone()函数。
而在很多情况,无法知道clone成员函数的确切名称,更灵活的方法是将clone函数作为sp的参数。
2. Copy on Write
sp中使用COW并不适合,因为sp不能区分对于被指向对象的const和non-const成员函数。
sp->ConstFun();
sp->NonConstFun();
先调用operatro->,再调用后面的函数。sp不知道是否要执行COW。函数调用超过sp的管理范围(如何超过的?)。sp过于底层不能有效的实现COW的语义。
3. Reference Counting
通常使得sp的size加倍,还有一个指针指向reference counter(同步问题)。
另一个容易被忽视的问题:rf的sp必须将reference counter保存在free store(点解?)。而reference counter很小,这样当allocator为它分配存储时速度很慢,而且浪费空间(点解?)。根源是查找可分配空间的算法慢,以及allocator为每一个chunk保存bookkeeping 信息所需的空间。
空间上的问题可以通过将pointer和referen count保存在一起。sp指向这个结构,但间接索引导致访问速度下降。
最有效的方式是将reference counter同被指对象保存在一起,称为:intrusive reference counting。这样必须修改被指对象类的结构,以支持rf。
4. Reference Linking
不需要真正记录指向某个对象的sp的数量,只需要知道是否为0。
所有的指向同一个对象的sp构成一个双向链表。每一个sp对象有两个额外的指针-prev和next。
优势:不需要格外的free store,更加可靠。
劣势:需要更多的空间来bookkeeping,速度也比rf慢,复制和删除需要进行链表操作。
Reference方法的致命缺陷是循环饮用--cyclic reference。
5. Destructive Copy
在copy时,销毁被copy的object。销毁源sp,将被指对象交给宿sp。std::auto_ptr就具有这种性质。事实上,这种用法比较危险。表现在哪里?
void Display(SmartPtr<Something> sp);
...
SmartPtr<Something> sp(new Something);
Display(sp); // sinks sp
尽管Display对它的参数sp并无恶意,但是由于Destructive Copy实现,调用之后sp变为空指针。悲惨。
Destructive Copy可以保证在任何时刻只有一个sp指向给定对象。
因为不支持value semantics,dc的sp不能在容器中存放,以近乎对待raw指针的方式来处理。
但也有它的好处:
1. 没有引入过多开销;
2. 强制ownership转移的语义。作为参数,表明function接过sp进行管理。
3. 作为函数返回值有优势。可以返回dc的sp,如果调用者不使用返回至,可以保证被指对象被销毁。
4. 像函数的stack变量一样有多条返回路径(?)。不需要手动删除被指对象,sp负责。
std::auto_ptr引入另一个优势;作为sp的唯一标准,程序员迟早要习惯它的行为。
上述sp的ownership policy中,默认策略为reference counting。