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

#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;
}

原文链接: https://www.cnblogs.com/lyxf/p/12358276.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

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

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/331595

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月1日 下午6:07
下一篇 2023年3月1日 下午6:07

相关推荐