您的位置:首页 > 财经 > 产业 > 外贸生意如何做_广东深圳手机号码_sem模型_seo网站制作优化

外贸生意如何做_广东深圳手机号码_sem模型_seo网站制作优化

2025/3/11 10:50:35 来源:https://blog.csdn.net/buuliuda/article/details/145999114  浏览:    关键词:外贸生意如何做_广东深圳手机号码_sem模型_seo网站制作优化
外贸生意如何做_广东深圳手机号码_sem模型_seo网站制作优化

3 weak_ptr 弱引用的智能指针

share_ptr虽然已经很好用了,但是有一点share_ptr智能指针还是有内存泄露的情况,当两个对象相互使用一个shared_ptr成员变量指向对方,会造成循环引用,使引用计数失效,从而导致内存泄漏。

weak_ptr 是一种不控制对象生命周期的智能指针, 它指向一个 shared_ptr 管理的对象。进行该对象的内存管理的是那个强引用的shared_ptr, weak_ptr只是提供了对管理对象的一个访问手段。weak_ptr 设计的目的是为配合 shared_ptr 而引入的一种智能指针来协助 shared_ptr 工作, 它只可以从一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析构不会引起引用记数的增加或减少。

weak_ptr 是用来解决shared_ptr相互引用时的死锁问题,如果说两个shared_ptr相互引用,那么这两个指针的引 用计数永远不可能下降为0,资源永远不会释放。它是对对象的一种弱引用,不会增加对象的引用计数, 和shared_ptr之间可以相互转化,shared_ptr可以直接赋值给它,它可以通过调用lock函数来获得 shared_ptr。

weak_ptr没有重载操作符*->,因为它不共享指针,不能操作资源,主要是为了通过shared_ptr获得资源的监测权,它的构造不会增加引用计数,它的析构也不会减少引用计数,纯粹只是作为一个旁观者来监视shared_ptr中管理的资源是否存在。weak_ptr还可以返回this指针。

3.1 基本用法

  1. 通过use_count()方法获取当前观察资源的引用计数,如下所示:

    shared_ptr<int> sp(new int(10));
    weak_ptr<int> wp(sp);
    cout << wp.use_count() << endl; //结果讲输出1
    
  2. 通过expired()方法判断所观察资源是否已经释放,如:

    shared_ptr<int> sp(new int(10));
    weak_ptr<int> wp(sp);
    if(wp.expired())cout << "weak_ptr无效,资源已释放";
    elsecout << "weak_ptr有效";
    
  3. 通过lock方法获取监视的shared_ptr,如:

    std::weak_ptr<int> gw;
    void f()
    {if(gw.expired()) {cout << "gw无效,资源已释放";}else {auto spt = gw.lock(); // 尝试将 std::weak_ptr 提升为 std::shared_ptr。如果关联的 std::shared_ptr 已经释放(引用计数为 0),则返回一个空的 std::shared_ptr。cout << "gw有效, *spt = " << *spt << endl;}
    }int main()
    {{auto sp = atd::make_shared<int>(42);gw = sp;f();}f();return 0;
    }
    

3.2 weak_ptr返回this指针

shared_ptr不能直接将this指针返回shared_ptr(会导致多个独立的 shared_ptr 实例管理同一个对象),需要通过派生 std::enable_shared_from_this类,并通过其方法shared_from_this来返回指针,原因是 std::enable_shared_from_this类中有一个weak_ptr,这个weak_ptr用来观察this智能指针,调用 shared_from_this()方法是,会调用内部这个weak_ptrlock()方法,将所观察的shared_ptr返回,范例:

// weak_ptr_reutrn_this.cpp
#include <iostream>
#include <memory>using namespace std;class A: public std::enable_shared_from_this<A>
{
public:shared_ptr<A> GetSelf() {return shared_from_this(); // 安全:返回与现有 shared_ptr 共享引用计数的 shared_ptr}~A(){cout << "Deconstruction A" << endl;}
};int main()
{// auto spp = make_shared<A>();shared_ptr<A> sp1(new A);shared_ptr<A> sp2 = sp1->GetSelf();  // 安全:sp1 和 sp2 共享引用计数//    shared_ptr<A> sp2;//    {//        shared_ptr<A> sp1(new A);//        sp2 = sp1->GetSelf();  // ok//    }cout << "sp1.use_count() = " << sp1.use_count()<< endl;cout << "sp2.use_count() = " << sp2.use_count()<< endl;return 0;
}
/*
sp1.use_count() = 2
sp2.use_count() = 2
Deconstruction A
*/

现在通过std::enable_shared_from_this 这个基类模板,安全地从对象内部获取一个 shared_ptr。这样就不会导致一个对象的资源被多个shared_ptr释放。
注意:获取自身智能指针的函数要在shared_ptr的构造函数被调用之后才能使用,因为 enable_shared_from_this内部的weak_ptr只有通过shared_ptr才能构造。

3.3 weak_ptr解决循环引用问题

shared_ptr的智能指针循环引用的问题,因为智能指针的循环引用会导致内存泄漏,可以通过 weak_ptr解决该问题,只要将A或B的任意一个成员变量改为weak_ptr。例如:

#include <iostream>
#include <memory>
using namespace std;class A;
class B;class A {
public:std::weak_ptr<B> bptr; // 修改为weak_ptrint *val;A() {val = new int(1);}~A() {cout << "A is deleted" << endl;delete  val;}
};class B {
public:std::shared_ptr<A> aptr;~B() {cout << "B is deleted" << endl;}
};//weak_ptr 是一种不控制对象生命周期的智能指针,
void test()
{std::shared_ptr<A> ap(new A);std::weak_ptr<A> wp1 = ap;std::weak_ptr<A> wp2 = ap;cout<< "ap.use_count()" << ap.use_count()<< endl;
}void test2()
{std::weak_ptr<A> wp;{std::shared_ptr<A> ap(new A);wp = ap;}cout<< "wp.use_count()" << wp.use_count() << ", wp.expired():" << wp.expired() << endl;if(!wp.expired()) {// wp不能直接操作对象的成员、方法std::shared_ptr<A> ptr = wp.lock(); // 需要先lock获取std::shared_ptr<A>*(ptr->val) = 20;  }
}int main()
{test2();
//    {
//        std::shared_ptr<A> ap(new A);
//        std::shared_ptr<B> bp(new B);
//        ap->bptr = bp;
//        bp->aptr = ap;
//    }cout<< "main leave" << endl;return 0;
}
/*
A is deleted
wp.use_count()0, wp.expired():1
main leave
*/

这样在对B的成员赋值时,即执行bp->aptr=ap;时,由于aptr是weak_ptr,它并不会增加引用计数,所以ap的引用计数仍然会是1,在离开作用域之后,ap的引用计数为减为0,A指针会被析构,析构后其内部的bptr的引用计数会被减为1,然后在离开作用域后bp引用计数又从1减为0,B对象也被析构,不会发生内存泄漏。

3.4 weak_ptr的使用注意事项

使用前需要检查是否合法,在使用weak_ptr前需要调用wp.expired()函数判断一下。 因为weak_ptr还仍旧存在,假如引用计数等于0,仍有某处“全局”性的存储块保存着这个计数信息。直到最后一个weak_ptr对象被析构,这块“堆”存储块才能被回收。例如:

weak_ptr<int> wp;  // 创建一个空的 weak_ptr
shared_ptr<int> sp_ok;  // 创建一个空的 shared_ptr
{shared_ptr<int> sp(new int(1));  // 创建一个 shared_ptr,管理一个 int 对象wp = sp;  // 将 weak_ptr 绑定到 shared_ptrsp_ok = wp.lock();  // 通过 weak_ptr 获取 shared_ptr
}
if (wp.expired()) {cout << "shared_ptr is destroy" << endl;
} else {cout << "shared_ptr no destroy" << endl;
}
// shared_ptr no destroy

sp_ok = wp.lock();当中由于 sp 仍然存在(引用计数为 1),wp.lock() 成功返回一个 shared_ptr,指向 sp 管理的对象。此时 sp_ok 的引用计数增加到 2spsp_ok 共享引用计数)。}(作用域结束)后sp 超出作用域,它的引用计数递减到 1(因为 sp_ok 仍然存在)于引用计数仍然为 1sp 管理的对象不会被释放。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com