C++ 智能指针实现原理
C++ 智能指针是通过 RAII(资源获取即初始化)技术来管理动态分配内存的工具,它能避免手动管理内存时常见的内存泄漏问题。下面详细介绍其两大核心机制:引用计数和自定义删除器。
一、 引用计数原理
引用计数是智能指针实现资源自动释放的基础机制。其工作流程如下:
- 当一个智能指针被创建并指向某个资源时,该资源的引用计数初始化为 1。
- 当智能指针被复制(如赋值给其他智能指针)或作为参数传递时,引用计数加 1。
- 当智能指针被销毁(如离开作用域)或被重置为指向其他资源时,引用计数减 1。
- 当引用计数降为 0 时,表示没有智能指针再引用该资源,此时自动释放该资源。
这种机制确保了资源的生命周期与引用它的智能指针数量严格绑定。C++ 标准库中的 std::shared_ptr
和 std::weak_ptr
就是基于引用计数实现的。
二、自定义删除器
默认情况下,智能指针在引用计数为 0 时会使用 delete
操作符释放资源。但对于一些特殊资源,如文件句柄、网络连接等,需要自定义释放方式,这时就可以使用自定义删除器。自定义删除器允许用户指定一个可调用对象(函数、函数对象或 Lambda 表达式),在资源释放时调用该对象来执行特定的清理操作。
三、 示例代码
下面是一个简单的示例,展示了引用计数和自定义删除器的用法:
#include <iostream>
#include <memory>// 自定义资源类,用于演示
class Resource {
public:Resource(int id) : id_(id) {std::cout << "Resource " << id_ << " created" << std::endl;}~Resource() {std::cout << "Resource " << id_ << " destroyed" << std::endl;}void use() const {std::cout << "Using resource " << id_ << std::endl;}
private:int id_;
};// 自定义删除器函数
void customDeleter(Resource* res) {std::cout << "Custom deleting resource" << std::endl;delete res;
}int main() {// 创建一个 shared_ptr,使用自定义删除器std::shared_ptr<Resource> ptr1(new Resource(1), customDeleter);std::cout << "ptr1 use count: " << ptr1.use_count() << std::endl;// 复制 shared_ptr,引用计数增加std::shared_ptr<Resource> ptr2 = ptr1;std::cout << "ptr1 use count: " << ptr1.use_count() << std::endl;std::cout << "ptr2 use count: " << ptr2.use_count() << std::endl;// 使用资源ptr1->use();ptr2->use();// 重置 ptr2,引用计数减少ptr2.reset();std::cout << "After reset ptr2:" << std::endl;std::cout << "ptr1 use count: " << ptr1.use_count() << std::endl;// ptr1 离开作用域,引用计数变为 0,资源被释放return 0;
}
四、代码解释
-
引用计数演示:
ptr1
创建时引用计数为 1。ptr2
复制ptr1
后,两者引用计数都变为 2。ptr2.reset()
使ptr2
不再引用资源,ptr1
的引用计数变回 1。ptr1
离开作用域时,引用计数降为 0,资源被释放。
-
自定义删除器演示:
- 通过
std::shared_ptr
的第二个参数传入customDeleter
函数。 - 当资源释放时,会先调用
customDeleter
函数,再执行实际的资源释放操作。
- 通过
通过这种方式,C++ 智能指针提供了一种安全且灵活的内存管理方式,既能自动管理资源生命周期,又能适应各种特殊资源的释放需求。