`

Efficient C++ 第十二章 引用计数

 
阅读更多
转自
http://blog.chinaunix.net/uid-25872711-id-3032607.html

Efficient C++ 第十二章 引用计数


    引用计数机制的实现,和其优劣。实现方式的特点,决定它不可能在任何情况下都有性能优势。
  应用编写过程中较多的使用指针的模块经常会遇到:内存泄漏、空指针(指针删除过早)的问题。为解决此类问题我们通常需要花费大量时间分析问题所在,小心的控制指针的分配和释放。
  引用计数的设计思想是:把对象清除的责任从客户端代码交给对象本身,它有一个引用计数器,程序中该对象只有一份内存,拷贝它只是对计数器+1,当计数器值为0时删除自己。

实现细节
  用BigInt做一个引用计数示例,BigInt把正整数表示为每一个十进制数的二进制编码。(不用关心它本身的细节)
  结构关系如下图:

    主要代码如下:
class BigInt {
friend BigInt operator+ (const BigInt&, const BigInt&);
public:
    BigInt (const char *);
    BigInt(unsigned = 0);
    BigInt (const BigInt&);
    BigInt& operator= (const BigInt&);
    BigInt& operator+= (const BigInt&);
    ~BigInt();

    char *getDigits() const { return digits; }
    unsigned getNdigits() const { return ndigits; }

private:
    char *digits;
    unsigned ndigits;
    unsigned size; // size of allocated string
    BigInt (const BigInt&, const BigInt&);// operational ctor
    char fetch(unsigned i) const;
};

//我们只需要关心类的以下几个函数实现
BigInt::BigInt (unsigned u)
{
    unsigned v = u;

    for (ndigits = 1; (v/=10) > 0; ++ndigits) {
        ;
        }

    digits = new char[size=ndigits];

    for ( unsigned i = 0; i < ndigits; ++i) {
        digits[i] = u%10;
        u /= 10;
        }
}
BigInt::~BigInt()
{
    delete [] digits;
}

BigInt& BigInt::operator= (const BigInt& rhs)
{
    if (this == &rhs) return *this;
    ndigits = rhs.ndigits;
    if (ndigits > size) {
       delete [] digits;
       digits = new char[size = ndigits];
       }

    for (unsigned i = 0; i < ndigits; ++i) {
        digits[i] = rhs.digits[i];
        }
    
    return *this;
}

    RCObject是用于引用计数的基类,它封装了引用计数变量及其有关操作。
class RCObject {
public:
    void addReference() { ++refCount;}
    void removeReference() { if (--refCount == 0) delete this;}

    void markUnshareable() { shareable = false;}
    bool isShareable() const { return shareable; }

    bool isShared() const { return refCount > 1; }

protected:
    RCObject() : refCount(0), shareable(true) {}
    RCObject(const RCObject& rhs) : refCount(0), shareable(true) {}
    RCObject& operator=(const RCObject& rhs) {return *this;}
    virtual ~RCObject() {}

private:
    int refCount;
    bool shareable;
};


    现在让BigInt从RCObject类继承,使其拥有引用计数特性。
class BigInt : public RCObject {
    // Same as before
};

    实现RCPtr模板类,注意->和*重载操作符的实现,它是一个智能指针:
template <class T>
class RCPtr {
public:
    RCPtr(T *realPtr = 0) : pointee(realPtr) { init();}
    RCPtr(const RCPtr& rhs) : pointee(rhs.pointee) { init();}
    ~RCPtr() { if (pointee) pointee->removeReference();}

    RCPtr& operator=(const RCPtr& rhs);

    T* operator->() const { return pointee; }
    T& operator*() const { return *pointee; }

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

template <class T>
void RCPtr<T>::init()
{
    if (0 == pointee) return;

    if (false == pointee->isShareable() ) {
       pointee = new T(*pointee);
       }

    pointee->addReference();
}

template <class T>
RCPtr<T>& RCPtr<T>::operator=(const RCPtr& rhs)
{
    if (pointee != rhs.pointee) {
       if (pointee) pointee->removeReference();
       pointee = rhs.pointee;
       init();
       }

    return *this;
}

    最后,我们有了实现引用计数BigInt的全部代码,实现RCBigInt非常简单,复杂的工作都交给RCPtr和RCObject完成。
class RCBigInt {
friend RCBigInt operator+ (const RCBigInt&, const RCBigInt&);
public:
    RCBigInt (const char *p) : value (new BigInt(p)) {}
    RCBigInt (unsigned u= 0) : value (new BigInt(u)) {}
    RCBigInt (const BigInt& bi) : value (new BigInt(bi)) {}
    
    void print() const { value->print(); }

private:
    RCPtr<BigInt> value;
};

inline
RCBigInt operator+ (const RCBigInt& left, const RCBigInt& right)
{
    return RCBigInt(*(left.value) + *(right.value));
}

从实现逻辑上可以看出,进行复制操作时引用计数类实际上只分配了一份内存,大量的复制操作情况下其性能优势比较明显。普通的一次一次分配新对象的情况,引用计数没有性能优势,反而因逻辑复杂化而性能受损。

对已存在的类实现引用计数
  上节对BigInt实现引用计数需要对BigInt做一定的修改,让它继承自RCObject。本节介绍不修改BigInt类的实现,因为很多情况下我们需要做引用计数的类是不允许我们进行修改的。
  这需要引用一个独立的类CountHolder,结构如下:
http://blog.chinaunix.net/attachment/201112/14/25872711_13238324240m0X.jpg


    实现一个新的智能指针RCIPtr,它和RCPtr基本相同。
class RCBigInt {
    ... // The same as before
private:
    RCIPtr<BigInt> value; // RCIPtr not RCPtr
};
template < class T>
class RCIPtr {
public:
    RCIPtr(T *realPtr = 0);
    RCIPtr(const RCIPtr& rhs);
    ~RCIPtr();

    RCIPtr& operator=(const RCIPtr& rhs);
    T* operator->() const { return counter->pointee; }
    T& operator*() const { return *(counter->pointee); }

private:
    struct CountHolder : public RCObject {
        ~CountHolder() { delete pointee; }
        T *pointee;
    };

    RCIPtr<T>::CountHolder *counter;
    void init();
};


template <class T>
void RCIPtr<T>::init()
{
    if (0 == counter) return;

    if (false == counter->isShareable() ) {
       counter = new CountHolder;
       counter->pointee = new T(*counter->pointee);
       }

    counter->addReference();
}

template <class T>
RCIPtr<T>::RCIPtr(T *realPtr)
    : counter(new CountHolder)
{
    counter->pointee = realPtr;
    init();
}

template <class T>
RCIPtr<T>::RCIPtr(const RCIPtr& rhs) : counter(rhs.counter)
{
    init();
}

template <class T>
RCIPtr<T>::~RCIPtr()
{
    if (counter) counter->removeReference();
}

template <class T>
RCIPtr<T>& RCIPtr<T>::operator=(const RCIPtr& rhs)
{
    if (counter != rhs.counter) {
       if (counter) counter->removeReference();
       counter = rhs.counter;
       init();
       }

    return *this;
}


    由于逻辑复杂化,引用计数对象创建时的开销增加了。
分享到:
评论

相关推荐

    Efficient C++

    《Efficient C++》是一本深受C++程序员喜爱的经典书籍,它主要关注如何在C++编程中实现高效、优化的代码。这本书的核心理念是帮助开发者理解C++的底层机制,以便编写出性能更高、资源利用更合理的程序。作者通过一...

    Efficient C++提高C++性能的编程技术.rar

    正确实现赋值运算符(`operator=`)的“深拷贝”和“浅拷贝”是关键,以防止引用计数错误和意外共享。 4. **常量与引用**:常量引用可以防止对对象的修改,提高代码的安全性。在函数参数中使用常量引用可以避免不必...

    Efficient C++ 英文 CHM 非扫描版

    Efficient C++ 英文 CHM 非扫描版 Dov Bulka David Mayhew

    Efficient C++中文版

    《Efficient C++中文版》作为一本专注于高效使用C++的书籍,其内容覆盖了C++编程中的许多高级概念和最佳实践。以下是对该书一些核心知识点的总结和解释: 1. 预处理器指令#define 预处理器指令#define用于定义宏。...

    Efficient C++: Performance Programming Techniques

    《Efficient C++: Performance Programming Techniques》是一本深入探讨如何在C++编程中实现高效性能的书籍。由IBM的资深软件专家Scott Meyers和Barbara E. Moo共同撰写,这本书结合了他们在处理高要求性能系统时...

    Efficient C++ Performance Programming Techniques.rar

    《Efficient C++ Performance Programming Techniques》是一本深入探讨C++性能优化的经典著作,作者是Scott Meyers。这本书针对C++程序员提供了许多实用的技巧和策略,帮助他们在编写代码时能够兼顾效率与性能。以下...

    Efficient C++ Performance Programming Techniques

    《Efficient C++ Performance Programming Techniques》是一本专为C++程序员设计的性能优化指南,它深入探讨了如何在C++编程中实现高效的代码执行。这本书不仅涵盖了基础的编程技巧,还涉及了许多高级主题,旨在帮助...

    Efficient.C++ Performance Programming Techniques

    《Effective C++:性能编程技术》是一本深受程序员喜爱的经典书籍,主要针对C++语言的高效性能优化提供了诸多实用技巧和建议。这本书深入探讨了如何通过优化代码来提高C++程序的运行效率,同时保持代码的清晰性和可...

    efficient c++电子版

    相当经典的一本C++书!学习C++必备。

    Modern and efficient C++ Thread Pool Library.zip

    "Modern and efficient C++ Thread Pool Library"很可能是一个第三方库,旨在提供比标准库更高级、性能更好的线程池实现。这个库可能包含以下关键知识点: 1. **线程池概念**:线程池是一组预先创建的线程,等待...

    Real-Time C++ Efficient Object-Oriented and Template Programming(3rd) 无水印原版pdf

    Real-Time C++ Efficient Object-Oriented and Template Microcontroller Programming(3rd) 英文无水印原版pdf 第3版 pdf所有页面使用FoxitReader、PDF-XChangeViewer、SumatraPDF和Firefox测试都可以打开 本...

    Effective C++ 3个版本清晰pdf

    - **第二版到第三版**:针对C++11及后续标准进行了更新,涵盖了新的语言特性,如lambda表达式、右值引用和类型推断等。 通过阅读这三个版本的《Effective C++》,程序员可以全面了解C++语言的发展历程,掌握从早期...

    Real-Time C++ Efficient Object-Oriented and Template Microcontroller Programming

    ### 实时C++:高效面向对象与模板微控制器编程 #### 标题解析与扩展知识点 **实时C++**:本书的主题围绕着如何利用C++语言进行高效的实时系统开发。实时系统是指那些对时间响应有严格要求的系统,通常用于工业控制...

    Efficient.C++Performance.Programming

    《Efficient C++ Performance Programming Techniques》是一本针对C++程序员的性能优化指南,由Scott Meyers撰写,是计算机科学的经典著作之一。这本书深入探讨了如何通过优化C++代码来提高程序运行效率,对于想要...

    Effective C++ 中文版第三版 高清PDF.pdf

    《Effective C++ 中文版第三版》是一本深入探讨C++编程实践的书籍,由Scott Meyers撰写,旨在帮助读者提升C++编程的效率和专业性。这本书的高清PDF版本提供了一个清晰易读的阅读体验,是C++程序员进阶学习的理想资料...

Global site tag (gtag.js) - Google Analytics