c++ 实现引用计数类的目的,原理及源码
Posted BBinChina
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++ 实现引用计数类的目的,原理及源码相关的知识,希望对你有一定的参考价值。
在c++开发过程中,经常需要记录对象的拥有者,因为只有其有责任删除该对象,即所有权的问题,为避免内存泄漏等问题,其他高级语言比如golang、java等实现了垃圾回收机制。在c++中可以通过实现引用计数来控制对象的生命周期,某种程度上也算是一种垃圾回收机制,如果面试吹牛时,你能这么个吹风,百万年薪不时梦(老套的广告语了)。
实际上,使用引用计数还有一目的:减少相同值对象的创建,比如java里的字符串string的字面值,当多个字面值一样时,不同的string对象实际上时指向同个内存地址。
Demo
#pragma once
#include "RCObject.h"
#include "RCPtr.h"
using namespace Concurrency;
class String {
public:
String(const char* initValue = "") :value(new StringValue(initValue)){
}
const char& operator[](int index) const {
return value->data[index];
}//只读
char& operator[](int index) {
//已被共享时,不影响其他使用者,需使用新的副本
if (value->isShared()) {
//Ptr的赋值构造函数会判断value的值是否需要释放
value = new StringValue(value->data);
}
value->markUnshareable();
return value->data[index];
}
private:
struct StringValue : public RCObject {
char* data;
StringValue(const char* initValue) {
init(initValue);
}
StringValue(const StringValue& rhs) {
init(rhs.data);
}
void init(const char* initValue) {
data = new char[strlen(initValue) + 1];
strcpy(data, initValue);
}
~StringValue() {
delete[] data;
}
};
RCPtr<StringValue> value;
};
以下为引用计数的实现
RCObject类
#pragma once
#include <atomic>
namespace Concurrency {
using namespace std;
class RCObject {
private:
std::atomic<int >refCount;//计数器
bool shareable;//是否共享
public:
void addReference();
void removeReference();
void markUnshareable();
bool isShareable() const;
bool isShared() const;
protected:
RCObject();
RCObject(const RCObject& rhs);
RCObject& operator=(const RCObject& rhs);
virtual ~RCObject() = 0;//纯虚函数
};
}
RCObject的实现
#include "RCObject.h"
namespace Concurrency {
RCObject::RCObject() : refCount(0), shareable(true)
{
}
RCObject::RCObject(const RCObject& rhs):refCount(0), shareable(true)
{
}
RCObject& RCObject::operator=(const RCObject& rhs)
{
// TODO: 在此处插入 return 语句
return *this;
}
void RCObject::addReference()
{
++refCount;
}
void RCObject::removeReference()
{
if (--refCount == 0) delete this;
}
void RCObject::markUnshareable()
{
shareable = false;
}
bool RCObject::isShareable() const
{
return shareable;
}
bool RCObject::isShared() const
{
return refCount > 1;
}
};
RCPtr类
#pragma once
namespace Concurrency {
template<typename T>//template<class T>
class RCPtr {
private:
T* pointee;
void init();
public:
RCPtr(T* realPtr = 0);//构造函数,默认值为0
RCPtr(const RCPtr& rhs);//拷贝构造函数, const表示被拷贝值不可修改
~RCPtr();
RCPtr& operator=(const RCPtr& rhs);//赋值构造
//模拟指针操作符
T* operator->() const;
T& operator*() const;
};
}
RCPtr实现
#include "RCPtr.h"
namespace Concurrency {
template<typename T>
void RCPtr<T>::init() {
}
template<typename T>
Concurrency::RCPtr<T>::RCPtr(T* realPtr):pointee(realPtr)
{
init();
}
template<typename T>
Concurrency::RCPtr<T>::RCPtr(const RCPtr& rhs):pointee(rhs.pointee)
{
init();
}
template<typename T>
Concurrency::RCPtr<T>::~RCPtr()
{
if (pointee) pointee->removeReference();
}
template<typename T>
RCPtr<T>& Concurrency::RCPtr<T>::operator=(const RCPtr& rhs)
{
// TODO: 在此处插入 return 语句
if (pointee != rhs.pointee) {
if (pointee) {
pointee->removeReference();
}
pointee = rhs.pointee;
init();
}
return *this;
}
template<typename T>
T* Concurrency::RCPtr<T>::operator->() const
{
return pointee;
}
template<typename T>
T& Concurrency::RCPtr<T>::operator*() const
{
// TODO: 在此处插入 return 语句
return *pointee;
}
}
以上是关于c++ 实现引用计数类的目的,原理及源码的主要内容,如果未能解决你的问题,请参考以下文章