参考 C++ 引用计数_vincent-xia的博客-优快云博客,完善了一些代码,写了一个push-pop程序测试
1.refCount.h
#pragma once
#include <iostream>
#include <string>
#include <mutex>
#include <thread>
using namespace std;
template<typename T>
class Referenced
{
public:
//初始化这个类,引用计数设为1,并且将p指向传入的地址
Referenced(T* pi)
{
refCount = 1;
p = pi;
}
//引用计数加1
int ref()
{
return ++refCount;
}
//引用计数减1
int unref()
{
return --refCount;
}
//返回引用计数
int count()
{
return refCount;
}
//析构函数,释放掉内存
~Referenced()
{
//cout << "delete referenced" << endl;
delete p;
p = nullptr;
}
public:
std::atomic<int> refCount = 0;//引用计数,表示有多少个变量引用这块内存
T* p = nullptr;//真实的指针
};
//对指针进行管理的类,持有一个Referenced类的指针ptr,根据ptr中的
//引用计数来判断是否调用delete来删除掉这个指针ptr
template<typename T, class D = default_delete<T>>
class Ref_ptr
{
public:
Ref_ptr() {
}
//使用int*指针初始化ptr,注意必须要放在初始化列表中
Ref_ptr(T* i) :ptr(new Referenced<T>(i))
{
//std::cout << "使用int*指针初始化ptr\n";
}
//拷贝构造函数,又有一个变量指向了这块内存
Ref_ptr(const Ref_ptr& rhs)
{
ptr = rhs.ptr;//将右操作数的引用计数对象赋值给左操作数
ptr->ref();//将它们的应用计数加1
}
//赋值操作符,右操作数的引用计数要减1,左操作数的引用计数要加1
Ref_ptr& operator=(const Ref_ptr& rhs)
{
if (&rhs == this)
return *this;
if (ptr && ptr->unref() == 0)//赋值操作符,首先将当前类的引用计数减1
{
//cout << "delete Ref_ptr" << endl;
delete ptr;
}
ptr = rhs.ptr;//将右操作数的引用计数赋值给当前对象
ptr->ref();//引用计数加1
return *this;
}
//析构函数,引用计数要减1,如果减为0,删除这块内存
~Ref_ptr()
{
if (!ptr)
return;
if (ptr->unref() == 0)
{
//cout << "delete Ref_ptr" << endl;
delete ptr;
ptr = nullptr;
}
}
using pointer = typename _Get_deleter_pointer_type<T, remove_reference_t<D>>::type;
pointer operator->() const noexcept {
if(ptr)
return ptr->p;
}
//返回引用计数
int count()
{
if(ptr)
return ptr->count();
}
private:
Referenced<T>* ptr;
};
2.test.cpp
#include "refCount.h"
#include <thread>
Ref_ptr<string> r;
Ref_ptr<string> r1;
std::mutex m;
#include<queue>
Ref_ptr<string> print(Ref_ptr<string> str) {
std::cout << str->size() << std::endl;
return str;
}
std::queue<Ref_ptr<string>> strqueue;
void gFunc1() {
while (1) {
std::string* str = new std::string("666888999999999999999999999999999999999999999999999999");
m.lock();
Ref_ptr<string> r = str;
strqueue.push(r);
m.unlock();
}
}
void gFunc2() {
while (1) {
m.lock();
Ref_ptr<string> str;
if (!strqueue.empty()) {
str = strqueue.front();
r = str;
strqueue.pop();
print(str);
}
m.unlock();
}
}
int main()
{
std::thread th1(gFunc1);
std::thread th2(gFunc2);
system("pause");
return 0;
}
测试过程中内存占用稳定在 1.5MB,说明申请的内存一直在释放,在push-pop过程中做到了内存的自动管理。

TODO:参照 std::shared_ptr 做的更完善一点,更深入理解std::shared_ptr。
文章介绍了使用C++实现一个基于引用计数的智能指针类`Ref_ptr`,该类能够自动管理内存,避免内存泄漏。通过`Referenced`类维护引用计数,并在`Ref_ptr`的构造、赋值和析构函数中调整计数,决定何时释放内存。文中还提供了一个多线程环境下的`push-pop`程序,测试了智能指针在并发情况下的内存管理效果,证明了其功能的正确性。
1513

被折叠的 条评论
为什么被折叠?



