栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

《More Effective C++》技术篇——Reference counting(引用计数)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

《More Effective C++》技术篇——Reference counting(引用计数)

  • Reference counting这项技术,允许多个等值对象共享同一实值。此技术的发展有两种动机,第一是为了简化heap object周边的簿记工作。它可以消除“记录对象拥有权”的负荷,因为当对象运用了reference counting技术,它便拥有它自己。一旦不再有任何人使用它,它便会自动销毁自己。reference counting的第二个发展动机则只是为了实现一种常识。如果许多对象有相同的值,将那个值存储多次是件愚蠢的事。最好是让所有等值对象共享一份实值就好。

  • 以下是一个包含了Copy-On-Write技术的Reference counting基类,有兴趣建议去看看原书中的文章,作者一步步引导写出这个类,写的很详细,这里因为篇幅原因就不赘述。

// RCObject.h
// template class,用来产生smart pointers-to-T objects;T必须继承自RCObject 
template
class RCPtr {
public:
    RCPtr(T* realPtr = 0);
    RCPtr(const RCPtr& rhs);
    ~RCPtr();

    RCPtr& operator=(const RCPtr& rhs);

    T* operator->() const;
    T& operator*() const;

private:
    T *pointee;
    void init();
};

// base class,用于reference-counted objects
class RCObject {
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;
    
private:
    int refCount;
    bool shareable;
};

// RCObject.cpp
RCObject::RCObject() : refCount(0), shareable(true) {

}

RCObject::RCObject(const RCObject& rhs) : refCount(0), shareable(true) {

}

RCObject& RCObject::operator=(const RCObject& rhs) {
    return *this;
}

RCObject::~RCObject () {

}

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;
}

template
void RCPtr::init () {
    if (pointee == 0)
        return;
    if (pointee->isShareable() == false) {
        pointee = new T(*pointee);
    }
    pointee->addReference();
}

template
RCPtr::RCPtr(T* realPtr) : pointee(realPtr) {
    init();
}

template
RCPtr::RCPtr(const RCPtr& rhs) : pointee(rhs.pointee) {
    init();
}

template
RCPtr::~RCPtr() {
    if (pointee) {
        pointee->removeReference();
    }
}

template
RCPtr& RCPtr::operator=(const RCPtr& rhs){
    if (pointee != rhs.pointee) {
        if (pointee) {
            pointee->removeReference();
        }
        pointee = rhs.pointee;
        init();
    }
    return *this;
}

template
T* RCPtr::operator->() const {
    return pointee;
}

template
T& RCPtr::operator*() const {
    return *pointee;
}
  • 然后,定义一个简单的String类,在String中包含表示其实值的struct StringValue,其中StringValue继承自上面的RCObject,使其拥有引用计数的能力。String代码如下所示。
// String.h
// 应用性class,这是应用程序开发人员接触的层面
#include 
#include "RCObject.h"
class String {
public:
    String(const char *initValue = "");

    const char& operator[] (int index) const;
    char& operator[] (int index);

private:
    // 以下struct用以表现字符串实值
    struct StringValue : public RCObject {
        char *data;

        StringValue(const char *initValue);
        StringValue(const StringValue& rhs);
        void init(const char *initValue);
        ~StringValue();
    };
    RCPtr value;
};

// String.cpp
void String::StringValue::init(const char *initValue) {
    data = new char[strlen(initValue) + 1];
    strcpy(data, initValue);
}

String::StringValue::StringValue(const char *initValue) {
    init(initValue);
}

String::StringValue::StringValue(const StringValue& rhs) {
    init(rhs.data);
}

String::StringValue::~StringValue() {
    delete [] data;
}

String::String(const char *initValue) : value(new StringValue(initValue)) {

}

const char& String::operator[](int index) const {
    return value->data[index];
}

char& String::operator[](int index) {
    if (value->isShared()) {
        value = new StringValue(value->data);
    }
    value->markUnshareable();
    return value->data[index];
}
  • 再来写个main,简单验证下。
#include 
#include 
int main()
{
    String s1 = "hello";
    String s2 = s1;

    std::cout << "s1[3] = " << s1[3] << std::endl;
    std::cout << "s2[3] = " << s2[3] << std::endl;

    s2[3] = 'x';

    std::cout << "s1[3] = " << s1[3] << std::endl;
    std::cout << "s2[3] = " << s2[3] << std::endl;
}
// 输出
s1[3] = l
s2[3] = l
s1[3] = l
s2[3] = x
  • Reference counting是个优化技术,其使用前提是:对象常常共享实值。如果这个假设失败,reference counting反而会赔上更多内存,执行更多代码。从另一个角度看,如果你的对象确实有“共同实值”的倾向,reference counting应可同时节省你的时间和空间。
  • 简单说,以下是使用reference counting改善效率的最适当时机:
    • 相对多数的对象共享相对少量的实值(必要)。
    • 对象实值的产生或销毁成本很高,或是它们使用许多内存(非必要)。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/649551.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号