寫時拷貝引用計數(shù)器模型-創(chuàng)新互聯(lián)

1、深淺拷貝的使用時機(jī):

創(chuàng)新互聯(lián)于2013年成立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目做網(wǎng)站、成都網(wǎng)站建設(shè)網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元金湖做網(wǎng)站,已為上家服務(wù),為金湖各地企業(yè)和個人服務(wù),聯(lián)系電話:028-86922220

 淺拷貝:對只讀數(shù)據(jù)共用一份空間,且只釋放一次空間;

 深拷貝:數(shù)據(jù)的修改,的不同空間;

2、引用計數(shù)器模型

 使用變量use_count,來記載初始化對象個數(shù);

 static模型(此處只用淺拷貝與淺賦值)

#include<iostream>
#include<string.h>
#include<malloc.h>
using namespace std;

class String{
public:
    String(const char *str = ""){
        if(str == NULL){
            data = new char;
            data[0] = 0;
        }else{
            data = new char[strlen(str) + 1];
            strcpy(data,str);
        }
        use_count++;     //每新創(chuàng)建一個對象,對引用計數(shù)器++;
    }
    String(const String &s){
        data = s.data;
        use_count++;      //創(chuàng)建出新的對象,use_count++;
    }
 //此處先不寫賦值語句
    ~String(){
        if(--use_count == 0){  //當(dāng)引用計數(shù)器減為0時,就是每次行析構(gòu)對象時,都對它減一次,直到為0才釋放空間,
            delete []data;
            data = NULL;
        }
    }
public:
    char* GetString()const{
        return data;
    }
private:
    char *data;
    static int use_count;   //此處use_count只有一份,負(fù)責(zé)記載創(chuàng)建了多少個對象;
};

int String::use_count = 0;  //C++中的靜態(tài)變量全局只有一份,可以再類外進(jìn)行初始化;

int main(void)
{
    String s1("hello");
    cout<<s1.GetString()<<endl;
    String s2;
    s2 = s1;  //淺賦值,調(diào)用默認(rèn)的;
    cout<<s2.GetString()<<endl;
    String s3("xyz"); //創(chuàng)建t3對象,要出問題了;(對其就只創(chuàng)建出來,不在進(jìn)行賦值語句等操作);此時的情況是:已經(jīng)有兩個對象,其成員data指向同一空間,此時又有一個data指向另一個空
                      //間,但是use_count為0才釋放空間,只釋放一份,所以肯定有內(nèi)存泄漏!??!
    return 0;
}

 上面的static淺拷貝其實存在很大的問題,當(dāng)t3對象創(chuàng)建時,use_count會加1;

 當(dāng)調(diào)用析構(gòu)函數(shù)時,每次減1,為0時,釋放空間,

寫時拷貝 引用計數(shù)器模型

3、寫時拷貝

 淺拷貝與深拷貝聯(lián)合使用,看實際需求對其編寫,此時我希望,對數(shù)據(jù)讀時共用一份數(shù)據(jù),需要修改時,在單獨開辟空間進(jìn)行修改,在進(jìn)行改寫,并且對象(初始化)應(yīng)該有自己的data和use_count,賦值語句時共用一份就行,此時就需要句柄了,這就是寫時拷貝;

 具體完整代碼如下:

#include<iostream>
#include<malloc.h>
#include<string.h>
using namespace std;
class String;
class String_rep{        // 這個類是封裝在內(nèi)部供我們程序員自己使用的。
    friend class String;  //友元類,可以訪問私有數(shù)據(jù)。
public:
    String_rep(const char *str = ""):use_count(0){  //構(gòu)造函數(shù)的初始化
        if(str == NULL){
            data = new char[1];
            data[0] = 0;
        }else{
            data = new char[strlen(str)+1];
            strcpy(data,str);
        }
    }
    String_rep(const String_rep &rep);
    String_rep& operator=(const String_rep &rep);
    ~String_rep(){
        delete []data;
        data = NULL;
    }
public:
    void increment(){  
        use_count++;
    }
    void decrement(){   //這個函數(shù)至關(guān)重要,寫了一個釋放空間的函數(shù),要在其后賦值語句中使用;
        if(--use_count == 0)
            delete this;
    }
    int use_count_()const{
        return use_count;
    }
public:
    char *getdata()const{
        return data;
    }
private:
    char *data;
    int use_count;
};
class String{
public:
    String(const char *str = ""):rep(new String_rep(str)){
        rep->increment();
    }
    String(const String &s){
        rep = s.rep;
        rep->increment();
    }
    String& operator=(const String &s){
        if(this != &s){
            rep->decrement();
            rep = s.rep;
            rep->increment();
        }
        return *this;
    }
    ~String(){
        rep->decrement();
    }
public:
    int use_count()const{
        return rep->use_count_();
    }
    void print()const{
        cout<<rep->data<<endl;
    }
    void toupper(){      //這個函數(shù)提供的意義:對其要改的對象重新申請空間,進(jìn)行改寫,使相互之間不影響。     
        if(rep->use_count_() > 1){ //對象個數(shù)大于1才進(jìn)行拷貝出來重新寫,只有一個就直接在其上進(jìn)行修改。
            String_rep *new_rep = new String_rep(rep->data);
            this->rep->decrement();
            rep = new_rep;
            rep->increment();
        }
        char *pch = rep->data;
        while(*pch){
            *pch -= 32;
            pch++;
        }
    }
private:
    String_rep *rep; // 句柄
};
int main(){
    String s1("hello");
    String s2 = s1;
    String s3("xyz");
    s3 = s2;
    s1.toupper();
    s1.print();
    cout<<"s1 count = "<<s1.use_count()<<endl;
    s2.print();
    cout<<"s2 count = "<<s2.use_count()<<endl;
    s3.print();
    cout<<"s3 count = "<<s3.use_count()<<endl;
    return 0;
}

以上的代碼就可以達(dá)到目的,每次創(chuàng)建對象都有自己的data和use_count(調(diào)用構(gòu)造函數(shù)),在賦值語句時先釋放原有空間,在進(jìn)行淺拷貝,構(gòu)造函數(shù)時也是淺拷貝,對其進(jìn)行了各自空間的管理與釋放,并且在修改數(shù)據(jù)時拷貝出來一份即可。

寫時拷貝 引用計數(shù)器模型

分析如下:

寫時拷貝 引用計數(shù)器模型

關(guān)于以上還有個問題:就是:

void decrement(){   
  if(--use_count == 0)
   delete this;
}

為什么不在String類的析構(gòu)函數(shù)中寫delete呢?

原因:析構(gòu)函數(shù)只有在對象釋放是才調(diào)用,而在此時,通過賦值語句要釋放空間,析構(gòu)函數(shù)此時就不能及時釋放原有空間,會造成內(nèi)存泄漏,所以寫一個釋放空間的函數(shù),內(nèi)部有delete,會先調(diào)用析構(gòu)函數(shù),達(dá)到了及時釋放空間的目的!

以上只是對寫時拷貝的粗淺理解。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

標(biāo)題名稱:寫時拷貝引用計數(shù)器模型-創(chuàng)新互聯(lián)
地址分享:http://bm7419.com/article46/hsehg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、品牌網(wǎng)站設(shè)計、商城網(wǎng)站用戶體驗、網(wǎng)站策劃、微信小程序

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司