详解C++中shared_ptr的使用教程

2020-01-06 15:14:25于海丽
shared_ptr能够记录对象被引用的次数,主要被用来管理动态创建的对象的销毁,这里我们就来详解C++中shared_ptr的使用教程,需要的朋友可以参考下  

shared_ptr是一种智能指针(smart pointer)。shared_ptr的作用有如同指针,但会记录有多少个shared_ptrs共同指向一个对象。
这便是所谓的引用计数(reference counting)。一旦最后一个这样的指针被销毁,也就是一旦某个对象的引用计数变为0,这个对象会被自动删除。这在非环形数据结构中防止资源泄露很有帮助。
auto_ptr由于它的破坏性复制语义,无法满足标准容器对元素的要求,因而不能放在标准容器中;如果我们希望当容器析构时能自动把它容纳的指针元素所指的对象删除时,通常采用一些间接的方式来实现,显得比较繁琐。boost库中提供了一种新型的智能指针shared_ptr,它解决了在多个指针间共享对象所有权的问题,同时也满足容器对元素的要求,因而可以安全地放入容器中。

总结下几个使用shared_ptr需要注意的问题:

一. 相互引用链


class C;
class B : public std::enable_shared_from_this<B>
{
public:
 ~B(){ cout << "~B" << endl; }
 void SetPC(std::shared_ptr<C>& pc){ _pc = pc; } 

private:
 std::shared_ptr<C> _pc;
};

class C : public std::enable_shared_from_this<C>
{
public:
 ~C(){ cout << "~C" << endl; }
 void SetPB(std::shared_ptr<B>& pb){ _pb = pb; }
 
private:
 std::shared_ptr<B> _pb;
};

int main()
{
 std::shared_ptr<C> pc = std::make_shared<C>();
 std::shared_ptr<B> pb = std::make_shared<B>();
 pc->SetPB(pb);
 pb->SetPC(pc);
 return 0;
}

上面的代码中,B和C均不能正确析构,正确的做法是,在B和C的释放函数,如Close中,将其包含的shared_ptr置空。这样才能解开引用链。

二. 自引用
还有个比较有意思的例子:


class C : public std::enable_shared_from_this < C >
{
public:

 ~C()
 {
  std::cout << "~C" << std::endl;
 }

 int32_t Decode(const char* data, size_t)
 {
  return 0;
 }
 void SetDecoder(std::function<int32_t(const char*, size_t)> decoder)
 {
  _decoder = decoder;
 }


private:
 std::function<int32_t(const char*, size_t)> _decoder;
};

int main()
{
 {
  std::shared_ptr<C> pc = std::make_shared<C>();
  auto decoder = std::bind(&C::Decode, pc, std::placeholders::_1, std::placeholders::_2);
  pc->SetDecoder(decoder);
 }
 // C不能正确析构 因为存在自引用
 return 0;
}

上面的C类包含了一个function,该function通过std::bind引用了一个std::shared_ptr,所以_decoder其实包含了一个对shared_ptr的引用。导致C自引用了自身,不能正确析构。需要在C的Close之类的执行关闭函数中,将_decoder=nullptr,以解开这种自引用。