当前位置: 首页 > article >正文

weak_ptr是否有计数方式,在哪分配的空间。

目录

前言

1. weak_ptr 的引用计数问题

2. 控制块和内存分配

3. weak_ptr 与 shared_ptr 的控制块关系


前言

  • weak_ptr 不增加对象的强引用计数,但会增加控制块的弱引用计数。
  • 如果使用 make_shared,控制块和对象在同一块内存中;使用 new 时,控制块和对象分配在不同的内存区域。
  • weak_ptr 通过 shared_ptr 的控制块管理弱引用计数,避免了循环引用的内存泄漏问题。

1. weak_ptr 的引用计数问题

“weak_ptr 真的不计数吗?”

严格来说,weak_ptr 确实不会增加对象的强引用计数。然而,这并不意味着它完全不涉及计数。事实上,weak_ptr 会参与弱引用计数的管理。

引用计数的细节

  • 强引用计数(use count):用于跟踪当前有多少个 shared_ptr 指向同一个对象。每创建一个新的 shared_ptr,强引用计数就增加;每销毁一个 shared_ptr,强引用计数就减少。当强引用计数为零时,管理的对象会被销毁。

  • 弱引用计数(weak count):用于跟踪当前有多少个 weak_ptr 指向同一个对象的控制块。弱引用计数不影响对象的生命周期,只是管理控制块的存在。当强引用计数和弱引用计数都为零时,控制块本身才会被销毁。

#include <iostream>
#include <memory>

int main() {
    std::shared_ptr<int> sp = std::make_shared<int>(10);
    std::weak_ptr<int> wp = sp;
    
    std::cout << "use_count: " << sp.use_count() << std::endl; // 输出 1
    std::cout << "weak_ptr use_count: " << wp.use_count() << std::endl; // 输出 1
    
    if (auto spt = wp.lock()) {  // 转换为 shared_ptr,增加强引用计数
        std::cout << "use_count after lock: " << sp.use_count() << std::endl; // 输出 2
    }
    
    std::cout << "use_count after lock is released: " << sp.use_count() << std::endl; // 输出 1
}

在这个示例中:

  • sp.use_count() 返回的是强引用计数(此处为1)。
  • wp.use_count() 返回的也是强引用计数(此处为1),但 wp 本身不增加这个计数。
  • wp.lock() 返回一个新的 shared_ptr,临时增加强引用计数,当这个临时 shared_ptr 释放时,强引用计数恢复。

2. 控制块和内存分配

“计数和控制块在哪里分配的空间?”

控制块(control block)是一个独立的结构体,通常包含以下内容:

  • 强引用计数(use count)
  • 弱引用计数(weak count)
  • 被管理的对象的指针
  • 自定义的析构函数等

内存分配的方式有两种:

1.使用 make_shared 初始化

当你使用 make_shared 时,控制块和实际对象通常分配在同一块内存中。这种方式优化了内存分配,减少了分配的次数,提高了性能。

auto sp = std::make_shared<int>(10);

这里,sp 的控制块和它管理的 int 对象是分配在一起的。

2.使用 newshared_ptr 构造函数初始化

如果你使用 new 创建对象,然后用 shared_ptr 构造函数管理这个对象,控制块和对象的内存是分开分配的。控制块由 shared_ptr 管理,但它与对象不在同一块内存中。

auto sp = std::shared_ptr<int>(new int(10));
  1. 这里,sp 的控制块与 int 对象位于不同的内存区域。

3. weak_ptrshared_ptr 的控制块关系

weak_ptr 共享 shared_ptr 的控制块,它不持有资源,但持有对控制块的弱引用。控制块中的弱引用计数用于确定何时可以安全地销毁控制块,而不是销毁对象本身。


http://www.kler.cn/a/289374.html

相关文章:

  • 前端知识点---Javascript的对象(Javascript)
  • 【韩老师零基础30天学会Java 】07章 面向对象编程(基础)
  • Node.Js+Knex+MySQL增删改查的简单示例(Typescript)
  • 文件上传漏洞--理论
  • 游戏引擎学习第五天
  • FMC 扩展子卡6 路 422,8 组 LVDS,8 路 GPIO
  • MacBook Pro M3 安装 Node.js v14 的兼容性
  • 进阶SpringBoot之 Shiro(6)整合 Thymeleaf
  • 【word导出带图片】使用docxtemplater导出word,通知书形式的word
  • 0基础学习爬虫系列:Python环境搭建
  • Anaconda的环境管理操作命令详解-学习篇
  • mysql创建数据库和表
  • list的简单实现
  • springblade-JWT认证缺陷漏洞CVE-2021-44910
  • 4.1 数据分析-excel 基本操作
  • Java语言程序设计基础篇_编程练习题**17.21 (十六进制编辑器)
  • LinkedList与链表
  • Java基于微信小程序的实习管理系统
  • C++ 设计模式——中介者模式
  • Django 安装指南
  • notepad++软件介绍(含安装包)
  • 力扣56-合并区间(Java详细题解)
  • Electron 项目实战 02:打包和自动更新
  • Linux下的VLC简介
  • 语言桥梁:探索全球最受欢迎的翻译工具,让理解更简单
  • MySQL复习3