码迷,mamicode.com
首页 > 编程语言 > 详细

c++智能指针-shared_ptr的尴尬-诞生weak_ptr

时间:2020-02-24 21:03:42      阅读:90      评论:0      收藏:0      [点我收藏+]

标签:操作   public   new   private   内存泄露   _id   weak   return   声明   

#include <iostream>
#include <memory>
#include <cassert>

//auto ptr
//shared_ptr
//unique_ptr
//weak_ptr

class Parent; //采用前置声明

using ParentPtr = std::shared_ptr<Parent>;
typedef std::weak_ptr<Parent> WeakParentPtr;

class Child {
    public:
//      ParentPtr father; //内存泄露
        WeakParentPtr father; //采用弱指针,则可以释放内存,不造成内存泄露
        Child() { std::cout << "Child!!" << std::endl; }
        ~Child();
};

typedef std::shared_ptr<Child> ChildPtr;
typedef std::weak_ptr<Child> WeakChildPtr;

class Parent {
    public:
        Parent() { std::cout << "Parent!!" << std::endl; }
        ChildPtr son;
//      WeakChildPtr son;

        void print() const { std::cout << "use_count: " << this->son.use_count() << std::endl;}
        ~Parent();
};

class Object {
    public:
        Object(int id) : m_id(id) { std::cout << "init obj " << m_id << std::endl; };
        ~Object() { std::cout << "bye bye " << m_id << std::endl; }
        int id() const { return m_id; }
    private:
        int m_id = 0;
};
using ObjectPtr = std::shared_ptr<Object>;

Child::~Child() { std::cout << "bye child!" << std::endl; }
Parent::~Parent() { std::cout << "bye parent!" << std::endl; }
//----------------------------------------------
void testParentAndChild() {
    ParentPtr p(new Parent());
    ChildPtr c(new Child());

//采用这种方式,造成内存泄露
    p->son = c; //智能指针拷贝, use_count + 1, c 的use_count 为 2
    p->print();
    c->father = p; //p 的 use_count 也为 2 了

//智能指针析构之后use_count  -1
//智能指针特性: 只有当use_count 变为0 时,才能释放掉管理的资源
//所以智能指针析构后,use_count 不为0,则造成了内存泄露
    ////////////
//只要打破环状的引用,则share_ptr就会很好的管理内存
}
//----------------------------------------------
//为了解决以上问题, 采用weak_ptr来解决
void sharedPtrWithWeakPtr() {
    ObjectPtr obj(new Object(1));
    typedef std::weak_ptr<Object> WeakObjectPtr;
    WeakObjectPtr weakObj(obj);//弱指针依赖于share_ptr,若share_ptr是有效的,则wake_ptr也是有效的.
    WeakObjectPtr weakObj2(obj);
    //而wake_ptr在进行赋值的操作运算的时候,并不影响use_count, 相当于只是作为监听者

    
    std::cout << "obj use count is " << obj.use_count() << std::endl;
    {
        auto p = weakObj.lock(); //相当于返回了一个 ObjectPtr类型,
        std::cout << "expired: " << weakObj.expired() << std::endl; //expierd() 查看监控的资源过期没有过期
        if(p) {
            std::cout << p.unique() << std::endl; //false, use_count >= 2, 因为auto p = ...,进行了一次指针拷贝, 
            //所以use_count + 1, 而weakObj.lock()返回若是有效的话,则use_count >= 1, 否则返回nullptr
            //则总体的就use_count >= 2
            //do what you wanna do  
        }else {
        
        
        }
    }
    obj.reset(); //obj 放弃管理的资源
    std::cout << "endl;";
    auto p2 = weakObj.lock(); //返回空,因为,obj不管理资源了
    
    obj.reset(new Object(2)); //重新管理另一个资源
    {
        auto p = weakObj.lock();
        if(p) {
            assert(false);
        }else {
            //要么资源已经释放,要么obj管理的资源跟换了.
            std::cout << "changed!" << std::endl;
        }

    }
    std::cout << "expired: " << weakObj.expired() << std::endl; //expierd() 查看监控的资源过期没有过期
}
int main(void) {
    testParentAndChild();
//  sharedPtrWithWeakPtr();
    return 0;
}

c++智能指针-shared_ptr的尴尬-诞生weak_ptr

标签:操作   public   new   private   内存泄露   _id   weak   return   声明   

原文地址:https://www.cnblogs.com/lyxf/p/12358276.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!