您现在的位置是:首页 > 正文

c++11之weak_ptr 使用介绍

2024-04-01 02:08:53阅读 3

介绍

weak_ptr是弱智能指针对象,它不控制所指向对象生存期的智能指针,它指向由一个shared_ptr管理的智能指针。将一个weak_ptr绑定到一个shared_ptr对象,不会改变shared_ptr的引用计数。一旦最后一个所指向对象的shared_ptr被销毁,所指向的对象就会被释放,即使此时有weak_ptr指向该对象,所指向的对象依然被释放。

这里写图片描述

代码验证如下:

//default consstructor
weak_ptr<string> wp;

{
    shared_ptr<string> p = make_shared<string>("hello world!\n");
    //weak_ptr对象也绑定到shared_ptr所指向的对象。
    wp = p;   
    cout << "use_count: " <<wp.use_count() << endl;
}
//wp是弱类型的智能指针,不影响所指向对象的生命周期,
//这里p已经析构,其所指的对象也析构了,因此输出是0
cout << "use_count: " << wp.use_count() << endl;

运行结果:

use_count: 1
use_count: 0

weak_ptr智能指针使用如下

void test_valid(weak_ptr<string> &wp)
{
    if(shared_ptr<string>  smptr2 = wp.lock())
    {
        cout << "the shared_ptr is valid\n";
    }
    else
    {
        cout << "the shared_ptr is not valid\n";
    }

    //检查被引用的对象是否已删除 false 仍存在  true 释放
    if(!wp.expired())
    {
        //it is getting valid shared_ptr obj now;
        shared_ptr<string>  smptr1 = wp.lock();
        cout << "   get obj value: " << *smptr1;
    }
}

int main()
{    
    shared_ptr<string> p = make_shared<string>("hello world!\n");

    //default consstructor
    weak_ptr<string> wp1;

    //copy constructor
    weak_ptr<string> wp2(p);

    //assign constructor
    weak_ptr<string> wp3 = wp2;

    test_valid(wp2);

    //释放被管理对象的所有权, 调用后 *this 不管理对象
    wp2.reset();

    test_valid(wp2);

    return 0;
}

运行结果:

the shared_ptr is valid
    get obj value: hello world!
the shared_ptr is not valid

循环引用

weak_ptr可以解决shared_ptr循环引用问题,导致内存泄漏问题,问题模型如下图:

这里写图片描述

当shared_ptr类型的spA、spB对象析构时,ref_count 减一;由于Obj A 和 Obj B中的shared_ptr智能指针还相互引用,导致ref_count不为零,spA和spB不会去析构所指的对象,最终导致内存泄漏。

当Obj A 和 Obj B中的智能指针是weak_ptr是,不会影响share_ptr智能指针引用计数,当spA和spB析构时,导致ref_count为零,同时所指向的对象也就被析构了;其解决方案模型如下:
这里写图片描述

代码实例如下:

//strong reference
class B;
class A
{
public:
    shared_ptr<class B> m_spB;
};


class B
{
public:
    shared_ptr<class A> m_spA;
};

//weak reference
class WeakB;
class WeakA
{
public:
    weak_ptr<class WeakB> m_wpB;
};


class WeakB
{
public:
    weak_ptr<class WeakA> m_wpA;
};


void test_loop_ref()
{
    weak_ptr<class A> wp1;

    {
        auto pA = make_shared<class A>();
        auto pB = make_shared<class B>();

        pA->m_spB = pB;
        pB->m_spA = pA;

        wp1 = pA;    
    }//内存泄漏

    cout << "wp1 reference number: " << wp1.use_count() << "\n";

    weak_ptr<class WeakA> wp2;
    {
        auto pA = make_shared<class WeakA>();
        auto pB = make_shared<class WeakB>();

        pA->m_wpB = pB;
        pB->m_wpA = pA;

        wp2 = pA;
    }//无内存泄漏

    cout << "wp2 reference number: " << wp2.use_count() << "\n";
}

int main()
{    
    //std::weak_ptr 用来避免 std::shared_ptr 的循环引用
    test_loop_ref();

    return 0;
}

wp1和wp2作为shared_ptr智能指针的核查器,其检测结果如下:

wp1 reference number: 1//内存泄漏
wp2 reference number: 0//问题解决

网站文章

  • 统一cas认证java_新版统一身份认证(CAS)

    申请需要提供以下信息,内容说明应用名称:格式为单位全称加应用,中间使用英文-连接,比如(学生处-离校系统),单位不需要再加厦门大学字样回调地址:格式为类似http://EXAMPLE.xmu.edu....

    2024-04-01 02:08:46
  • Mybatis设计分析一

    Mybatis设计分析一

    前面文章主要针对mybatis的进阶的使用有了个大的了解,包括缓存自定义 以及开启二级缓存机制,以及如何达到多数据源,按照我之前的写法通过路由 去解决 不同的数据源的问题,当然可以,有些时候其实也不用...

    2024-04-01 02:08:39
  • 两万常用汉字的拼音+首字母缩写+unicode编码对照表

    最近做项目遇到一项需求,为了隐藏汉字,对医院名称使用首字母代替,对医生名称用拼音代替。查阅了众多资料,比较分散,也不规范,做一个统一,问题包括以下几方面:1. 读出汉字的拼音首字母可通过Excel 公式实现;2. 读出汉字的拼音实现方法,基本需要借助编程,但是目前网上流传最广的版本是比较老旧的版本,不仅编码覆盖不全,而且有错误的mapping。3. 得到2万个常用的汉字并不容易,最...

    2024-04-01 02:07:59
  • Java参数传递

    要点 读完所有的评论以后,问题终于明白了,至少在一个主要问题上产生了混淆。某些评论认为我的节选是错的,因为对象是按引用传递的。 对象确实是按引用传递的;节选与这没有冲突。节选中说所有 参数都是按值 -- 另一个参数 -- 传递的。下面的说法是正确的:在 Java 应用程序中永远不会传递对象,而只传递对象引用。因此是按引用传递对象。但重要的是要区分参数是如何传递的,这才是该节选的意图。Java 应用

    2024-04-01 02:07:52
  • 【模板】用HTML编写邮件正文 | 各大邮箱几乎都会过滤css样式、js脚本等效果,如何用基础HTML编写?

    【模板】用HTML编写邮件正文 | 各大邮箱几乎都会过滤css样式、js脚本等效果,如何用基础HTML编写?

    2024-04-01 02:07:45
  • Javase | 字符编码、转义字符、方法执行过程中的 “内存分配”

    Javase | 字符编码、转义字符、方法执行过程中的 “内存分配”

    字符编码、转义字符、在控制台上输出 “反斜杠字符”、在控制台上输出 “单引号字符”、方法执行过程中的 “内存分配”.....

    2024-04-01 02:07:06
  • python 脚本第一行怎么写

    一、 python脚本第一行的写法:【#!/usr/bin/env python】。该语句告诉操作系统执行该脚本时,首先到env设置里查找python的安装路径,然后调用对应路径下的解释器程序完成操作...

    2024-04-01 02:06:59
  • jszip压缩服务器文件,使用JSZip压缩驻留在服务器上的PDF

    对不起,在这篇文章中缺少链接:这是我在stackoverflow上的第一篇文章,正如错误消息所说,“[我]需要至少10个声望才能发布2个以上的链接。”下载PDF(或任何二进制文件),你可以使用xhr....

    2024-04-01 02:06:52
  • linux mtp 代码,Linux MTP 的故事

    Linux下面有许许多多糟糕的故事,输入法算是其中之一,不过今天我们要讲的是另外一个故事。这个故事本质上和KDE关系不大,不过也算让我纠结了许久了。首先来介绍一下MTP,MTP是Media Trans...

    2024-04-01 02:06:15
  • Docker私房菜————Docker Compose| Compose安装和使用|快速单机编排|

    Docker私房菜————Docker Compose| Compose安装和使用|快速单机编排|

    目录 1.概念1.1 Docker Compose是什么1.2 YAML1.3 yml 文件配置指令参考1.4 Compose命令说明 2.compose的安装和使用2.1 安装compose2.2...

    2024-04-01 02:06:07