惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
MyScale Blog
MyScale Blog
Microsoft Security Blog
Microsoft Security Blog
量子位
B
Blog
aimingoo的专栏
aimingoo的专栏
Apple Machine Learning Research
Apple Machine Learning Research
阮一峰的网络日志
阮一峰的网络日志
The GitHub Blog
The GitHub Blog
T
The Exploit Database - CXSecurity.com
N
News | PayPal Newsroom
Cloudbric
Cloudbric
A
About on SuperTechFans
AI
AI
Hacker News: Ask HN
Hacker News: Ask HN
S
Schneier on Security
Recent Commits to openclaw:main
Recent Commits to openclaw:main
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Cyber Attacks, Cyber Crime and Cyber Security
L
LINUX DO - 最新话题
T
The Blog of Author Tim Ferriss
Simon Willison's Weblog
Simon Willison's Weblog
有赞技术团队
有赞技术团队
H
Heimdal Security Blog
J
Java Code Geeks
大猫的无限游戏
大猫的无限游戏
D
Docker
Security Archives - TechRepublic
Security Archives - TechRepublic
N
News and Events Feed by Topic
IT之家
IT之家
Know Your Adversary
Know Your Adversary
N
Netflix TechBlog - Medium
T
Tailwind CSS Blog
B
Blog RSS Feed
C
Cybersecurity and Infrastructure Security Agency CISA
C
Cisco Blogs
博客园 - 叶小钗
美团技术团队
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
H
Hackread – Cybersecurity News, Data Breaches, AI and More
L
LangChain Blog
The Hacker News
The Hacker News
Y
Y Combinator Blog
I
Intezer
The Register - Security
The Register - Security
F
Full Disclosure
V
V2EX
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Last Week in AI
Last Week in AI
Martin Fowler
Martin Fowler

博客园 - xcywt

IT人备考心得分享 一个大龄程序员的回乡记 一种刚接触的语法。只在linux可用 固件打包流程 malloc底层实现以及和new的比较 C++异步调用 future async promise packaged_task 如果在单例模式中返回share_ptr ??? 记录一道面试题(哈希表 稀疏矩阵) Qt实现自定义控件-按钮 一个线程池的例子 C++ 条件变量condition_variable的例子 C++14的一些新特性 C++11的一些特性 ubuntu编译grpc & protobuf perf笔记 一个cmakelist的例子(自动处理多个proto) Linux下eCal测试计划及进度记录 windows编译ecal 记录一次重装gitlab
C++中share_ptr中循环引用的问题
xcywt · 2024-09-19 · via 博客园 - xcywt

背景:

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。

循环引用的例子:

#include <stdio.h>
#include <iostream>
#include <memory>

class Child;
class Parent;

class Parent
{
private:
    std::shared_ptr<Child> ChildPtr = nullptr;
    //std::weak_ptr<Child> ChildPtr;
public:
    Parent() { printf("Parent() +++++++++++++ \n"); }
    ~Parent() { printf("~Parent() +++++++++++++ \n"); }
    void SetChild(std::shared_ptr<Child> sp) { ChildPtr = sp; }
};
class Child
{
private:
    std::shared_ptr<Parent> ParentPtr = nullptr;
public:
    Child() { printf("Child() +++++++++++++ \n"); }
    ~Child() { printf("~Child() +++++++++++++ \n"); }
    void SetParent(std::shared_ptr<Parent> sp) { ParentPtr = sp; }
};

void shareTest()
{
    printf("shareTest +++++++++++++ \n");
    {
        std::shared_ptr<Parent> p(new Parent);
        std::shared_ptr<Child> c(new Child);
        printf("构造完成 ... \n");
        p->SetChild(c);
        c->SetParent(p);
        printf("p use count:%d\n", p.use_count());
        printf("c use count:%d\n", c.use_count());
    }
    printf("shareTest +++++++++++++ \n");
    system("pause");
}

int main()
{
  shareTest();
  return 0;
}

运行结果:

可以看到在出了作用域后,p和c并没有被释放。

使用weak_ptr解决这个问题:

 运行结果: