Smart Pointer and MultiThread in CPP

Smart Pointer

智能指针用于管理heap上对象的生命周期。

  • std::auto_ptr: ptr:对象=1:1, ptr引用的对象可以转移(通过拷贝或赋值)(C++11已被废弃,使用std::unique_ptr代替)。
  • boost::scoped_ptr: ptr:对象=1:1, ptr引用的对象不可转移。
  • boost::shared_ptr: ptr:对象=N:1, 内置引用计数器。无法解决循环引用。
  • boost::weak_ptr: ptr:对象=N:1, 可以手工解决循环引用。

后三个在std::tr1中也提供。

weak_ptr只能通过shared_ptrweak_ptr创建,因此其必须对应一个shared_ptr,但是不会增加shared_ptr的引用计数,因此是一个弱引用。weak_ptr通过提升/lock()获得对应的shared_ptr。如果对象已释放,则返回空的shared_ptr

shared_ptr避免循环引用通常的做法是:如果是

1
2
3
        ---(shared_ptr)---->
owner                          child
        <--(shared_ptr)-----

的情况,则设计成:

1
2
3
        ---(shared_ptr)---->
owner                           child
        <---(weak_ptr)-----

MultiThread

shared_ptr
1
2
3
4
5
6
7
template<class T> class shared_ptr
{
...
private:
    T * px;                     // contained pointer
    detail::shared_count pn;    // reference counter
}

shared_ptr有两个数据成员,pn是引用计数器。 shared_ptr的计数操作是安全且无锁的原子操作。 因此在多线程中通过拷贝或赋值操作创建新的shared_ptr对象是安全的,能够正确记录引用的值。

1
2
3
4
5
// thread A
shared_ptr<int> p2(p); // reads p

// thread B
shared_ptr<int> p3(p); // read p, OK, multiple reads are safe

上面代码读取了同一个shared_ptr对象,结果是正确的。 但是同一个shared_ptr被多个线程写入时,结果就未定义了(因为有两个成员,pn并不是执行计数操作,而是被赋值),这时就需要加锁。 shared_ptr对象的析构也算写入操作。

Reference