2.由深拷贝和浅拷贝引发的写时拷贝技术

一、相关问题

  我们知道,浅拷贝会引发重复释放,导致程序崩溃。而深拷贝虽不会出现上述问题,但是内存空间开销大。所以,有没有一种方法,

  既节省空间,又不会造成程序崩溃呢?

二、写时拷贝技术

  写时拷贝(Copy-on-write):如果有多个呼叫者同时要求相同资源,他们会共同取得相同的指标指向相同的资源,直到某个呼叫者

                                          尝试修改时,才会复制一个副本给该呼叫者。

三、例子

  实现string类,在string中添加引用计数器类成员 

class String;
//引用计数器类
class String_rep
{
    friend class String;
    friend ostream& operator<<(ostream& out, String const& s);
public:
    String_rep(const char* str = "")
        : m_UseCount(0){
        if(NULL == str){
            m_data = new char[1];
            m_data[0] = '\0';
        }else{
            m_data = new char[strlen(str) + 1];
            strcpy_s(m_data, strlen(str) + 1, str);
        }
    }
    String_rep(String_rep const& that){
        m_data = new char[strlen(that.m_data) + 1];
        strcpy_s(m_data, strlen(that.m_data) + 1, that.m_data);
    }
    String_rep& operator=(String_rep const& rhs){
        if(this != &rhs){
            delete[] m_data;
            m_data = new char[strlen(rhs.m_data) + 1];
            strcpy_s(m_data, strlen(rhs.m_data) + 1, rhs.m_data);
        }
        return *this;
    }
    ~String_rep(){
        delete[] m_data;
        m_data = NULL;
    }
public:
    void Increment(){ ++m_UseCount; }
    void Decrement(){
        if(--m_UseCount == 0){
            delete this;
        }
    }
private:
    char* m_data;
    int m_UseCount;
};
class String
{
    friend ostream& operator<<(ostream& out, String const& s){
        return out << s.m_rep->m_data;
    }
public:
    String(const char* str = ""){
        m_rep = new String_rep(str);
        m_rep->Increment();
    }
    String(const String& that){
        m_rep = that.m_rep;
        m_rep->Increment();
    }
    String& operator=(String const& rhs){
        if (this != &rhs){
            m_rep->Decrement();
            m_rep = rhs.m_rep;
            m_rep->Increment();
        }
        return *this;
    }
    ~String(){
        m_rep->Decrement();
    }
public:
    void ToUpper(){
        if (m_rep->m_UseCount > 1){
            String_rep* newRep = new String_rep(m_rep->m_data);
            m_rep->Decrement();
            m_rep = newRep;
            m_rep->Increment();
        }
        char* ch = m_rep->m_data;
        while (*ch != '\0'){
            *ch -= 32;
            ++ch;
        }
    }
private:
    String_rep* m_rep;
};
int main()
{
    String s1("hello");
    String s2 = s1;
    String s3("world");
    s3 = s2;
    cout << "s1 = " << s1 << endl;
    cout << "s2 = " << s2 << endl;
    cout << "s3 = " << s3 << endl;
    cout << "----------------------------" << endl;
    s2.ToUpper();
    cout << "s1 = " << s1 << endl;
    cout << "s2 = " << s2 << endl;
    cout << "s3 = " << s3 << endl;
    system("pause");
    return 0;
}

  运行结果:

  

 

posted @ 2016-08-11 16:38  甩锅侠  阅读(211)  评论(0编辑  收藏  举报