C++中的引用计数机制
C++中的引用计数机制
引用计数是为了防止内存泄露而产生的。基本想法是对于动态分配的对象,进行引用计数,每当增加一次对同一个对象的引用,那么引用对象的引用计数就会增加一次,每删除一次引用,引用计数就会减一,当一个对象的引用计数减为零时,就自动删除指向的堆内存。
在C++中,手动释放资源,不是最佳实践。因为我们很有可能就忘记了去释放资源而导致泄露。所以通常的做法是对于一个对象而言,我们在构造函数的时候申请空间,而在析构函数(在离开作用域时调用)的时候释放空间,也就是我们常说的 RAII 资源获取即初始化技术。凡事都有例外,我们总会有需要将对象在自由存储上分配的需求,在传统 C++ 里我们只好使用 new 和 delete 去对资源进行释放。
引用计数是这样一个技巧,它允许多个有相同值的对象共享这个值的实现。
这个技巧有两个常用动机:
- 简化跟踪堆中的对象的过程
- 第二个动机是如果很多对象有相同的值,更好的办法是让所有的对象共享这个值的实现。这么做不但节省内存,而且可以使得程序运行更快。
class String {
public:
String(const char *value = "");
String& operator=(const String &rhs);
private:
char *data;
};
String a = b = c = d = e = "Hello";
根据这个实现,我们可以推测,这 5 个对象及其值如下:



引用计数的实现
C++11 引入了智能指针的概念,使用了引用计数的机制,让程序员不再需要关心手动释放内存。这些智能指针就包括 std::shared_ptr/std::unique_ptr/std::weak_ptr。
在C++11中新增的智能指针shared_ptr中采用引用计数的方法,记录当前内存资源被多少个智能指针引用。该引用计数的内存在堆上分配。当新增一个时引用计数加1,当过期时引用计数减1。只有引用计数为0时,智能指针才会自动释放引用的内存资源。
以下是智能指针shared_ptr的简单实现:
template<typename T>
class SharedPtr {
public:
// 构造函数
SharedPtr(T *ptr = nullptr) : m_ptr(ptr), m_count(new int(1)) {}
// 拷贝构造函数
SharedPtr(const SharedPtr<T>& rhs) {
this->m_count = rhs.m_count;
this->m_ptr = rhs.m_ptr;
++(*m_count);
}
// 赋值运算符
SharedPtr<T>& operator=(const SharedPtr<T>& rhs) {
(*rhs.m_count)++;
if (--(*m_count) == 0) {
delete m_ptr;
ptr = nullptr;
delete m_count;
m_count = nullptr;
}
m_ptr = rhs.m_count;
m_count = rhs.m_count;
return *this;
}
T& operator*() {
return *m_ptr;
}
T* operator->() {
return m_ptr;
}
~SharedPtr() {
if (--(*m_cout) == 0) {
delete m_ptr;
m_ptr = nullptr;
delete m_count;
m_count = nullptr;
}
}
private:
T* m_ptr; // 封装一个普通指针
int *m_count; // 指向引用计数
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!