C++ - 强引用和弱引用

Juce源码分析-弱引用(1) <br />     弱引用估计大家平时在c++编程中用的时候不是很多,但是很多脚本语言采用这种方法,比如Lua和Squirrel,可以参看我对Squirrel的翻译文档,其中专门有一节讲述弱引用的,有弱引用那么就有强引用,这显然是一个相对的概念,到底什么是强引用和弱引用呢,以前没有学过,在网上搜了一下,在java的讲述中有这个概念,说真没看明白,按照我的理解,我觉得可以这么很简单的理解:<br />     强引用:直接和被指向的生命期绑定,一般都以指针的形式体现,如果它指向的地址或者对象空间已经被释放, 阅读详情
AI摘要

本文探讨了 C++ 中引用计数的概念及其重要性,详细解释了强引用与弱引用的区别,以及如何利用弱引用解决循环引用导致的内存泄漏问题。

原来,我认为“为什么会有引用计数这样的技术”是为了内存自动回收和节省内存,但是读完下面的几节后,内存自动回收是一个原因,但是节省内存并不是真正的原因,真正的原因是有些对象如果被复制在现实中是不合事实的。


为什么有引用计数

    C++中存在两种语义:值语义(value sematics)和对象语义(object sematic),对象语义也可以叫做引用语义(reference sematics)。
值语义,指的是对象的拷贝与原对象无关,就像拷贝int一样,C++的常用类型数据等都是值语义。
对象语义,指的是面向对象意义下的对象,是禁止拷贝的。

    在设计一个类的时候该类是否可以被拷贝(即具备拷贝构造函数),取决于拷贝后的语义是否成立,比如一个Thread类,拷贝后系统中并不会启动另外一个线程,所以拷贝是禁止的。同样类似于Employee雇员类也是。

    这么设计起码有两个好处:

    1. 语义合理,有些对象复制是不符合常理的

    2. 节省内存


强引用

当对象被创建时,计数为1;每创建一个变量引用该对象时,该对象的计数就增加1;当上述变量销毁时,对象的计数减1,当计数为0时,这个对象也就被析构了。
强引用计数在很多种情况下都是可以正常工作的,但是也有不凑效的时候,当出现循环引用时,就会出现严重的问题,以至于出现内存泄露,如下代码:
#include <string>
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>

class parent;
class children;

typedef boost::shared_ptr<parent> parent_ptr;
typedef boost::shared_ptr<children> children_ptr;

class parent
{
public:
    ~parent() { std::cout <<"destroying parent\n"; }

public:
    children_ptr children;
};

class children
{
public:
    ~children() { std::cout <<"destroying children\n"; }

public:
    parent_ptr parent;
};

void test()
{
    parent_ptr father(new parent());
    children_ptr son(new children);

    father->children = son;
    son->parent = father;
}

void main()
{
    std::cout<<"begin test...\n";
    test();
    std::cout<<"end test.\n";
}

运行该程序可以看到,即使退出了test函数后,由于parent和children对象互相引用,它们的引用计数都是1,不能自动释放,并且此时这两个对象再无法访问到。这就引起了c++中那臭名昭著的内存泄漏。
一般来讲,解除这种循环引用有下面有三种可行的方法:
1. 当只剩下最后一个引用的时候需要手动打破循环引用释放对象。
2. 当parent的生存期超过children的生存期的时候,children改为使用一个普通指针指向parent。
3. 使用弱引用的智能指针打破这种循环引用。
虽然这三种方法都可行,但方法1和方法2都需要程序员手动控制,麻烦且容易出错。下面就介绍弱引用

弱引用

boost::weak_ptr<T>是boost提供的一个弱引用的智能指针,它的声明可以简化如下:
namespace boost {

    template<typename T> class weak_ptr {
    public:
        template <typename Y>
        weak_ptr(const shared_ptr<Y>& r);

        weak_ptr(const weak_ptr& r);

        ~weak_ptr();

        T* get() const; 
        bool expired() const; 
        shared_ptr<T> lock() const;
    }; 
}

可以看到,boost::weak_ptr必须从一个boost::share_ptr或另一个boost::weak_ptr转换而来,这也说明,进行该对象的内存管理的是那个强引用的boost::share_ptr。boost::weak_ptr只是提供了对管理对象的一个访问手段。boost::weak_ptr除了对所管理对象的基本访问功能(通过get()函数)外,还有两个常用的功能函数:expired()用于检测所管理的对象是否已经释放;lock()用于获取所管理的对象的强引用指针。
由于弱引用不更改引用计数,类似普通指针,只要把循环引用的一方使用弱引用,即可解除循环引用。对于上面的那个例子来说,只要把children的定义改为如下方式,即可解除循环引用:
class children
{
public:
    ~children() { std::cout <<"destroying children\n"; }

public:
    boost::weak_ptr<parent> parent;
};
最后值得一提的是,虽然通过弱引用指针可以有效的解除循环引用,但这种方式必须在程序员能预见会出现循环引用的情况下才能使用,也可以是说这个仅仅是一种编译期的解决方案,如果程序在运行过程中出现了循环引用,还是会造成内存泄漏的。因此,不要认为只要使用了智能指针便能杜绝内存泄漏。毕竟,对于C++来说,由于没有垃圾回收机制,内存泄漏对每一个程序员来说都是一个非常头痛的问题。
将Dify平台开发的工作流集成到Open WebUI中 将Dify开发的工作流集成到Open WebUI是一个能够显著增强AI应用交互能力和业务逻辑深度的有效途径。其核心在于通过API建立两者间的通信桥梁,并确保API在格式、协议和行为上的一致性,特别是向OpenAI Chat API规范看齐。最简单直接的路径是利用Dify的“对话型”或“Agent型”应用,这类应用的API设计更倾向于满足Open WebUI这类聊天前端的期望。然而,面对复杂的现实场景,直接的完美兼容并非总是唾手可得。 阅读详情

相关推荐

Unity新手必看:5分钟搞定TextMeshPro中文乱码,告别小方块(附7000+常用字库)

本文详细介绍了Unity中TextMeshPro中文乱码问题的解决方案,包括快速生成中文字体的步骤和优化技巧。通过使用支持中文的.ttf字体文件和自定义字符集,开发者可以在5分钟内解决TMP显示小方块的问题,提升游戏或应用的文本显示效果。

weixin_33095355的博客 362

C++11:弱引用智能指针

弱引用智能指针可以看做是的助手,它不管理内部的指针。没有重载操作符 * 和 ->,因为它不共享指针,不能操作资源,所以它的构造不会增加引用计数,析构也不会减少引用计数,它的主要作用就是作为一个旁观者监视 shared_ptr 中管理的资源是否存在。1.1 初始化在 C++11 中,;构造了一个空 weak_ptr 对象;通过一个空 weak_ptr 对象构造了另一个空 weak_ptr 对象;通过一个 shared_ptr 对象构造了一个可用的 weak_ptr 实例对象。...

oorik的博客 1256

麒麟系统grub被锁怎么办?双密码遗忘救援指南(实测V10 SP3版本)

本文详细介绍了麒麟系统V10 SP3版本在GRUB和root密码双遗忘情况下的救援指南。通过ISO镜像进入救援模式,结合单用户模式操作,实现密码重置与系统权限恢复,特别适用于等保合规环境。

384

C++11特新:弱引用智能指针

弱引用智能指针可以看做是s的助手,它不管理内部的指针。没有重载操作符和,因为它不共享指针,不能操作资源,所以它的构造不会增加引用计数,析构也不会减少引用计数,它的主要作用就是作为一个旁观者监视中管理的资源是否存在。

qq_73185160的博客 1197

【冷冻电镜】RELION5.0使用教程总结

对于您自己的数据,您可能希望使用各种倾斜系列对齐方法,然后比较每种方法生成的断层扫描图像的质量(参见下一步)。通过检查 CtfFind job 的 tilt_series 目录中的star文件来检查几个倾斜系列的散焦值。GitHub上也有人反应这个问题,目前我的解决方案是下载了较低版本的CTFFIND的,降级到4.1.10可以成功运行。此外,logfile.pdf 文件包含所有显微照片的有用参数图,例如散焦、像散、估计分辨率等,以及整个数据集中这些值的直方图。的目录,以及指向此目录的符号链接。

进阶中的程序员吃吃的博客 4222

WSL2离线安装Ubuntu终极指南:绕过Microsoft Store慢速下载(附最新22.04 LTS离线包)

本文提供WSL2离线安装Ubuntu 22.04 LTS的完整指南,帮助开发者绕过Microsoft Store下载慢的问题。通过PowerShell命令配置环境、获取离线安装包并完成安装,同时包含初始配置、资源优化及常见问题解决方案,助您快速搭建高效的Linux开发环境。

c8d9e0f1的博客 899

智能指针weak_ptr

开始之前先看一段代码, struct A { std::shared_ptr<B>pointer; ~A() { std::cout<< "A被销毁"<<std::end; } }; struct B { std::shared_ptr<A>pointer; ~B() { std::cout<< "B被销毁"<<std::end; } }; int ma

yizhiniu_xuyw的专栏 1279

镜头像差之五——场曲

什么是场曲? 场曲[curvature of field] 物面上所有的点经过系统后,最佳焦点位置不在同一平面上,若这些像点所成的面为曲面,则称为系统有场曲。 与物高二次方、入射光瞳口径一次方成正比的像差。若仅存在场曲,则所有物平面上的点都有相应的像点,但分布在一个球面上;若采用弯成此种形状的底片,则可获得处处清晰的像。此时在理想像平面上,像点呈现为圆斑。 第一张图是最简单也是最容易理解的场曲,也就是对焦点锐利,其余部分逐渐松散,但实际上大多现代镜头的场曲都呈现为图二的形态:对焦点与边缘锐度.

camerall 1万+

c++弱引用与强引用

https://www.zhihu.com/question/26851369 智能指针一个很重要的概念是“所有权”,所有权意味着当这个智能指针被销毁的时候,它指向的内存(或其它资源)也要一并销毁。这技术可以利用智能指针的生命周期,来自动地处理程序员自己分配的内存,避免显示地调用delete,是自动资源管理的一种重要实现方式。 为什么要引入“弱引用”...

aikb6223的博客 572

pytorch搭建SSAE实现预测分类代码模板完整代码

pytorch搭建SSAE实现预测分类代码模板完整代码

323

贪婪投影三角化算法

贪婪投影三角化算法是一种利用点云数据进行曲面重建的方法。其基本思想是通过迭代地连接点云中的邻近点来生成三角形,从而构建出整个表面。这种方法被称为“贪婪”,因为它在每一步仅考虑当前最优的策略,而不考虑全局的最优性。

twnkie的博客 1567

1分钟理清C/C++的弱符号和强符号,弱引用和强引用

1分钟理清C/C++的弱符号和强符号,弱引用和强引用

大道至简,求同存异 1734

基于Simulink的光伏+储能家庭能源管理系统仿真

本文通过Simulink建模,分析了家庭光伏+储能系统的优化调度问题。针对光伏发电与用电高峰不匹配导致电费节省有限的问题,构建了包含5kW光伏、10kWh电池和6kW负荷的完整模型,设计了无控、规则控制和24小时经济优化三种策略。仿真结果显示,经济优化策略可使日电费降低32%,光伏自用率从45%提升至89%,尤其在晚高峰时段能显著减少高价购电。文章详细介绍了物理层建模、分时电价实现和控制策略设计方法,并探讨了天气预测、V2H等高级扩展功能,为家庭能源智能管理提供了实用解决方案。

xiaoheshang_123的博客 188

【C++】强引用和弱引用

链接器处理强引用和弱引用的过程几乎是一样的,只是对于未定义的弱引用,链接器不认为它是一个错误,一般默认其为 0(地址为 0),或者是一个特殊的值,以便程序代码能够识别。 __attribute__((weak)) extern int a; printf("a = %d\n", a); 我们可以将它编译成一个可执行文件,GCC 并不会报链接错误。但是当程序运行时,输出&amp;a: 0, ...

王磊的博客 2340

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

C++中强引用和弱引用

C++中的智能指针有weak_ptr和shared_ptr之分。一般情况下我们使用shared_ptr比较多,weak_ptr也是带有引用计数的智能指针,但是是不增加对象的引用计数,即弱引用,主要用来解决shared_ptr存在循环引用的时候会出现内存泄漏的问题。 只要存在shared_ptr指向对象,该对象就不会析构,直到shared_ptr析构或reset()时才会被销毁。 见下面代码: #i...

qq_26548003的博客 2339

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

php弱引用是什么意思,C++_浅谈C语言中的强符号、弱符号、强引用和弱引用,首先我表示很悲剧,在看《程 - phpStudy...

浅谈C语言中的强符号、弱符号、强引用和弱引用首先我表示很悲剧,在看《程序员的自我修养--链接、装载与库》之前我竟不知道C有强符号、弱符号、强引用和弱引用。在看到3.5.5节弱符号和强符号时,我感觉有些困惑,所以写下此篇,希望能和同样感觉的朋友交流也希望高人指点。首先我们看一下书中关于它们的定义。引入场景:(1)文件A中定义并初始化变量i(int i = 1), 文件B中定义并初始化变量i(int ...

weixin_28884741的博客 127

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

C++实现对象和接口的弱引用

弱引用是相对于强引用而言,它引用一个对象但是又不控制对象的生存时期,然后在使用时需要先检查引用的对象是否还存在。而强引用,一般是基于引用计数,引用计数明确的控制了对象的生存时期。如果按控制关系排一个顺序,就是:强引用控制对象生存时期,对象生存时期控制弱引用是否有效,弱引用则什么也没控制,它本身就是一个对象(例如C#里的System.WeakReference),高级一点可以是个模板。   弱引用

namespace MatrixLife { 2126

Java 中的强引用、弱引用、软引用和虚引用

引用方式内存不足时垃圾回收机制启动时其余情况强引用否否否软引用是否否弱引用是是否虚引用可能可能可能在一般的程序中,弱引用和虚引用很少会被用到,强引用天天都在用就不必我说了,在有些情况下(如资源文件很大,但并不是全部要在同一时刻使用)我们会使用软引用来代替原来的强引用,一是可以避免某些情况下产生的 OOM,此外,它可以减少程序使用的内存,加速程序的运行。

小康2022的博客 257

弱引用与强引用

引用节省内存并不是真正的原因,真正的原因是有些对象如果被复制在现实中是不合事实的。 为什么有引用计数     C++中存在两种语义:值语义(value sematics)和对象语义(object sematic),对象语义也可以叫做引用语义(reference sematics)。 值语义,指的是对象的拷贝与原对象无关,就像拷贝int一样,C++的常用类型数据等都是值语义。 对象语

Gease_lcj的博客 1651

智能指针和弱引用

 智能指针和弱引用在android中可以广泛看到的template<typenameT> classSp句柄类实际上是android为实现垃圾回收机制的智能指针。智能指针是c++中的一个概念,因为c++本身不具备垃圾回收机制,而且指针也不具备构造函数和析构函数,所以为了实现内存(动态存储区)的安全回收,必须对指针进行一层封装,而这

醉月 3792

dll的弱引用和强引用

先描述下dll的创建方法 Test.h和Test.cpp #pragma once #ifdef __COMMON #define __COMMON_EXPORT __declspec(dllexport) #else #define __COMMON_EXPORT __declspec(dllimport) #endif extern "C" __...

weixin_33800593的博客 82

Java强软弱虚四大引用 以及 与 c++ 智能指针的对比

强引用:默认引用类型,确保对象不会被 GC 回收。软引用:用于实现缓存,内存不足时可能会被回收。弱引用:用于避免内存泄漏,对象可能随时被 GC 回收。虚引用:用于跟踪对象的回收状态,配合使用。这些不同类型的引用在内存管理和应用程序优化中有各自的用途,开发者可以根据需求选择合适的引用类型来管理对象的生命周期和资源。

抟土成人祖,炼石补青天。眼中览银河,手可摘星辰。 1165

弱引用和强引用

如果目标文件对外部目标文件符号进行强引用,但在链接成可执行文件时不能被正确的决议(好奇怪的名称,看看p_51),链接器就会报错,这是对于强引用(Strong Reference)而言的。 与之相对应还有一种弱引用(Weak Reference),在处理弱引用时,如果该符号有定义,则链接器将对该符号的引用进行决议,如果该符号未被定义,则链接器对于该引用不报错。 链接器处理强引用和弱引用的过程几乎...

weixin_33896726的博客 174
上一篇: 都用WebKit也并不意味Web的统一:WebKit的前世今生
下一篇: MP3文件格式解析
G机器猫
博客等级 码龄16年 106粉丝 74原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值