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 的控制块,它不持有资源,但持有对控制块的弱引用。控制块中的弱引用计数用于确定何时可以安全地销毁控制块,而不是销毁对象本身。

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值