**More Effective C++ 29. Reference Counting

其实是看的迷迷糊糊

#include <string.h>

template<class T>
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();
};


class RCObject {
public:
    RCObject();
    RCObject(const RCObject& rhs);
    RCObject& operator=(const RCObject& rhs);
    virtual ~RCObject() = 0;

    void addReference();
    void removeReference();

    void markUnshareable();
    bool isShareable() const;

    bool isShared() const;

private:
    size_t refCount;
    bool shareable;
};

class String {
public:
    String(const char *value = "");

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

private:
    struct StringValue :public RCObject {
        char *data;
        StringValue(const char *initValue);
        StringValue(const StringValue& rhs);
        void init(const char *initValue);
        ~StringValue();
    };
    RCPtr<StringValue> value;
};

// the implementation of RCObject
RCObject::RCObject() : refCount(0), shareable(true) { }
RCObject::RCObject(const RCObject&) : refCount(0), shareable(true) { }
RCObject& RCObject::operator=(const RCObject  &) { 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; }


// the implementation of RCPtr
template<class T>
void RCPtr<T>::init() {
    if (pointee == 0) return;
    if (pointee->isShareable() == false) {
        pointee = new T(*pointee);
    }
    pointee->addReference();
}

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

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

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

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

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

template<class T>
T& RCPtr<T>::operator*() const { return *pointee; }

// the implement of String::StringValue
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; }

// the implement of String
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];
}
template<class T> 
class RCIPtr {
public:
    RCIPtr(T* realPtr = );
    RCIPtr(const RCIPtr& rhs);
    ~RCIPtr();

    RCIPtr& operator = (const RCIPtr& rhs);
    T* operator->() const;
    T& operator*() const;
    RCObject& getRCObject() { return *counter; }
private:
    struct CountHolder : public RCObject {
        ~CountHolder() { delete pointee; }
        T *pointee;
    };
    CounterHolder *counter;
    void init();
};

template<class T> 
void RCIPtr<T>::init() {
    if (counter->isShareable() == false) {
        T* oldValue = counter->pointee;
        counter = new CountHolder;
        counter->pointee = oldValue ? new T(*oldValue) : 0;
    }
    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() { counter->removeReference(); }

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

template<class T>
T* RCIPtr<T>::operator->() const { return counter->pointee; }

template<class T>
T& RCIPtr<T>::operator*() const { return *(counter->pointee); }
class Widget {
public:
    Widget(int size);
    Widget(const Widget& rhs);
    ~Widget();
    Widget& operator=(const Widget& rhs);
    void doThis();
    int showThat() const;
};

class RCWidget {
public:
    RCWidget(int size):value(new Widget(size)) { }
    void doThis() {
        if (value.getRCObject().isShared()) {
            value = new Widget(*value);
        }

        value->doThis();
    }
    int showThat()const { return value->showThat(); }
private:
    RCIPtr<Widget> value;
};
#ifndef GUARD_Ptr_h
#define GUARD_Ptr_h

// Ptr.h
#include <iostream>
#include <stdexcept>

template <typename T> class Ptr {
    public:
        // new member to copy the object conditionally when needed
        void make_unique() {
            if (*refptr != 1) {
                --*refptr;
                refptr = new size_t(1);
                p = p ? p->clone() : 0;
            }
        }

        // same as Ref_handle
        Ptr(): p(0), refptr(new size_t(1)) { }
        Ptr(T* t): p(t), refptr(new size_t(1)) { }
        Ptr(const Ptr& h): p(h.p), refptr(h.refptr) { ++*refptr; }

        Ptr& operator=(const Ptr&);
        ~Ptr();
        operator bool() const { return p; }
        T& operator*() const; 
        T* operator->() const {
            if (p)
                return p;
            throw std::runtime_error("unbound Ptr");
        }

    private:
        T* p;
        std::size_t* refptr;
};

template <typename T> 
Ptr<T>& Ptr<T>::operator=(const Ptr& rhs) {
    ++*rhs.refptr;

    // free the left-hand side, destroying pointers if appropriate
    if (--*refptr == 0) {
        delete refptr;
        delete p;
    }

    // copy in values from the right-hand side
    refptr = rhs.refptr;
    p = rhs.p;
    return *this;
}

template <typename T>
T& Ptr<T>::operator*() const {
    if (p)
        return *p;
    throw std::runtime_error("unbound Ptr");
}

template <typename T>
Ptr<T>::~Ptr() {
    if (--*refptr == 0) {
        delete refptr;
        delete p;
    }
}

#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值