C++ shared_ptr

原创 2016年08月30日 11:35:50
        std::shared_ptr属于STL库,它的作用和auto_ptr相似,也是管理一个对象指针,提供一个释放内存的封装操作,但是它可以和其他shared_ptr对象共享对指针的管理。
它的实现原理是再内部维护一个引用计数,当引用计数为0的时候进行释放销毁操作。
        std::shared_ptr的构造函数有多重,我们常用的是默认构造函数和带有指针参数的构造函数:
        
default (1)
constexpr shared_ptr() noexcept;
from pointer (3)
template <class U> explicit shared_ptr (U* p);
默认的构造函数初始化引用为0,带有指针参数的构造函数初始化引用为1。另外拷贝构造函数:
copy (6)
shared_ptr (const shared_ptr& x) noexcept;
template <class U> shared_ptr (const shared_ptr<U>& x) noexcept;
如果x不为空,那么引用计数在x的基础上加1。如果x为空,那么本次构造为默认构造,引用计数为0:
    std::shared_ptr<int> pTest; //默认构造.
    std::shared_ptr<int> pTest2(nullptr); //默认构造
    std::shared_ptr<int> pTest3(pTest);   //默认构造

    std::shared_ptr<int> pTest4(new int(10)); //引用为1
    std::shared_ptr<int> pTest5(pTest4);      //引用为2

        std::shared_ptr在操作符=的实现中同样会对引用计数进行操作,原理和构造函数差不多。
        到这里我们已经可以清楚地知道std::shared_ptr可以共享所有权,并且用引用计数来进行管理,当引用计数为0的时候才会进行释放操作,那么就可能造成一种引用环路问题,我们用一个网上的例子(http://blog.csdn.net/shanno/article/details/7363480):

#include <iostream>
#include <memory>

class Woman;
class Man 
{
private:
    std::weak_ptr<Woman> _wife;
    //std::shared_ptr<Woman> _wife;
public:
    void setWife(std::shared_ptr<Woman> woman)
    {
        _wife = woman;
    }

    void doSomthing()
    {
        if (_wife.lock())
        {
        }
    }

    ~Man() 
    {
        std::cout << "kill man\n";
    }
};

class Woman
{
private:
    //std::weak_ptr<Man> _husband;
    std::shared_ptr<Man> _husband;
public:
    void setHusband(std::shared_ptr<Man> man) 
    {
        _husband = man;
    }
    ~Woman() {
        std::cout << "kill woman\n";
    }
};


int main(int argc, char** argv) 
{
    std::shared_ptr<Man> m(new Man());
    std::shared_ptr<Woman> w(new Woman());
    if (m && w) 
    {
        m->setWife(w);
        w->setHusband(m);
    }
    return 0;
}

        在Man类内部会引用一个Woman,Woman类内部也引用一个Man。当一个man和一个woman是夫妻的时候,他们直接就存在了相互引用问题。man内部有个用于管理wife生命期的shared_ptr变量,也就是说wife必定是在husband去世之后才能去世。同样的,woman内部也有一个管理husband生命期的shared_ptr变量,也就是说husband必须在wife去世之后才能去世。这就是循环引用存在的问题:husband的生命期由wife的生命期决定,wife的生命期由husband的生命期决定,最后两人都死不掉,违反了自然规律,导致了内存泄漏。
        要解决这个问题我们就需要认识std::weak_ptr。std::weak_ptr同样是一种智能指针,但是是为了配合shared_ptr工作而存在的。它可以从一个shared_ptr或者weak_ptr中来构造,但是并不会改变引用计数
  
default (1)
constexpr weak_ptr() noexcept;
copy (2)
weak_ptr (const weak_ptr& x) noexcept;
template <class U> weak_ptr (const weak_ptr<U>& x) noexcept;
from shared_ptr (3)
template <class U> weak_ptr (const shared_ptr<U>& x) noexcept;
它比较重要的成员函数是expired和lock。expired是用来检查从属的shared_ptr是否已经析构(删除empty),lock是在expired返回值为true(从属的shared_ptr没有被删除)的情况下,返回一个从事的shared_ptr临时对象,这个临时对象的产生同样会使原来的shared_ptr引用计数增加,所以我们在实际操作中一定要控制这个临时产生的shared_ptr的生命周期。
        我们如果用weak_ptr来解决上述问题就比较简单了,在环路引用中改变一个引用为weak_ptr,不增加引用计数,在使用的时候仅仅临时产生一个shared_ptr对象来进行操作,当然如果在这个临时对象的声明周期没有销毁前原来的shared_ptr销毁了,那么管理的指针会延迟到这个临时shared_ptr销毁的时候销毁。
        和std::shared_ptr相关的比较常用的方法有:
        std::shared_ptr<int> pTest6 = std::make_shared<int>(new int());
        std::shared_ptr<A> pFather = std::dynamic_pointer_cast<B>(pChild);//static_pointer_cast const_point_cast形式差不多。

        std::shared_ptr更方便地管理内存,我们不需要再考虑析构时的顺序问题了,完全交给智能指针来管理,大大减少了程序猿的负担,减少bug的产生。

相关文章推荐

C++基础::shared_ptr 编程细节(一)

1. shared_ptr 的两面性(类实例,“指针”) 2. shared_ptr 的一个副作用 3. 以 shared_ptr 类类型为容器类型的容器之间的赋值...

说说C++智能指针(1): 关于shared_ptr

shared_ptr是新的标准库的一个主要成员,作为一个非嵌入式的智能指针,其设计可谓已经是绞尽脑汁。当然,还有很多人对它提出了不满。没有完美的设计,只有合适的设计。1. shared_ptr最大的特...

Effective C++之std::tr1::shared_ptr的使用

Effective C++之std::tr1::shared_ptr的使用

C++ - "shared_ptr"的使用方法 及 代码

"shared_ptr"的使用方法 及 代码   智能指针(smart pointer)是C++11的新特性. 指针在无人使用时, 自动释放动态内存. 通过"use_count"计数, 并判断是否无人...

C++之智能指针shared_ptr

今天看到Mozilla的SharedPtr.h的实现方式,花了点时间,看懂了,写篇博客,以备记录。 SharedPtr.h中封装的是谷歌的base中的linked_ptr。 主要代码如下: ...

C++ 11智能指针之shared_ptr

 shared_ptr是一个引用计数智能指针,用于共享对象的所有权。它可以从一个裸指针、另一个shared_ptr、一个auto_ptr、或者一个weak_ptr构造。还可以传递第二个参数给sh...

C++ 共享指针 shared_ptr

shared_ptr 由于C++不像java一样有自动回收内存机制,new对象后,都要手动的delete掉,当程序员忘记delete的时候,可能会发生访问内存异常错误。shared_ptr是为了...

C/C++ 日常学习总结(第二十一篇)智能指针shared_ptr

最近看到项目中很多封装的 1.auto_ptr

C++简单版shared_ptr智能指针的实现

sp_counted_base.h#pragma once class sp_counted_base//管理对象引用计数 { public: sp_counted_base() :count...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++ shared_ptr
举报原因:
原因补充:

(最多只允许输入30个字)