2.智能指针,里面的计数器何时会改变
🔬 智能指针引用计数机制详解
📖 内容概览
智能指针通过引用计数机制自动管理对象的生命周期,确保资源得到正确的分配和释放。本文将深入探讨引用计数在各种场景下的变化规律。
🎯 核心概念
智能指针将一个引用计数器与类指向的对象相关联,引用计数跟踪共有多少个类对象(如 shared_ptr 对象)共享同一指针。
🔄 引用计数变化时机
📋 对象创建时
- 触发条件:当创建类的新对象时
- 计数变化:初始化指针,并将引用计数设置为 1
- 示例:
std::shared_ptr<int> ptr1 = std::make_shared<int>(42); // 计数 = 1📋 复制构造时
- 触发条件:当对象作为另一个对象的副本时
- 计数变化:复制构造函数复制副本指针,并增加与指针相应的引用计数(+1)
std::shared_ptr<int> ptr2 = ptr1; // 计数 = 2 (ptr1 和 ptr2 共享同一对象)📋 赋值操作时
- 触发条件:使用赋值操作符对一个对象进行赋值时
- 处理流程:
- 先判断是否是自己给自己赋值
- 使左操作数的指针的引用计数减1(因为指针已指向别处)
- 如果减1后引用计数为0,则释放指针所指对象内存
- 然后增加右操作数所指对象的引用计数(因为左操作数现在指向右操作数的对象)
std::shared_ptr<int> ptr3 = std::make_shared<int>(100); // 计数 = 1ptr3 = ptr1; // ptr3 原指向对象计数-1,ptr1 指向对象计数+1📋 析构函数调用时
- 触发条件:调用析构函数时(对象超出作用域、显式删除等)
- 计数变化:析构函数先使引用计数减1,如果减至0则delete对象
{ std::shared_ptr<int> ptr4 = ptr1; // 计数 = 3} // ptr4 析构,计数 = 2🔄 引用计数变化流程
创建新对象 ──────→ 计数 = 1 ↓复制构造 ────────→ 计数 + 1赋值操作 ────────→ 左操作数计数 - 1,右操作数计数 + 1析构函数 ────────→ 计数 - 1,若为0则释放对象🎯 关键要点
| 操作类型 | 计数变化 | 说明 |
|---|---|---|
| 创建 | 设置为1 | 首次拥有对象 |
| 复制 | +1 | 新增一个拥有者 |
| 赋值 | 左-1,右+1 | 转移所有权 |
| 析构 | -1,为0时释放 | 释放最后一个拥有权 |
🔍 深入理解
引用计数机制是智能指针(特别是 shared_ptr)实现自动内存管理的核心。它确保:
- 只有当没有任何
shared_ptr指向对象时才释放对象 - 避免内存泄漏和悬空指针
- 实现资源的自动管理,符合RAII原则
⚠️ 注意事项
- 自赋值检查很重要,避免不必要的引用计数变化
- 线程安全:
shared_ptr的引用计数操作是原子的 - 循环引用问题:使用
weak_ptr解决循环引用 通过精确控制引用计数的变化,智能指针能够在适当的时机自动释放资源,极大地简化了C++程序的内存管理。