c++寫時拷貝
阿新 • • 發佈:2019-02-03
為什麼要用寫時拷貝?
在c++中一個類有六個預設成員函式,其中拷貝建構函式分為淺拷貝和深拷貝;
淺拷貝是一種值拷貝,深拷貝不僅是值拷貝,還要做其他處理;
深淺拷貝的區別:
由上圖可知當一個拷貝構造一個需動態開闢空間的物件時,用淺拷貝時會出現同一塊空間被釋放兩次,這樣顯然有問題,用深拷貝的話可以解決此問題,但當拷貝構造出來的物件,不需要修改時,使用深拷貝就有些浪費空間了,採用引用計數的寫時拷貝能更好的解決問題。
如何實現寫時拷貝?
寫時拷貝,按其意思來說就是在“寫”(修改)的時候進行拷貝,它要實現的是既不浪費空間,又不使同一空塊空間析構多次;因此它才用引用計數的方法來實現寫時拷貝;(以string類為例)
具體程式碼如下:
#define _CRT_SECURE_NO_WARNINGS 1 #include using namespace std; class String { public: String(const char *str="") :_str(new char[strlen(str)+1]) ,_refcount(NULL) { strcpy(_str,str); _refcount=new int(1); } String(const String& s) :_str(s._str) ,_refcount(NULL) { _refcount=s._refcount; (*_refcount)++; } String& operator=(const String& s) { if(_str!=s._str) { Release(); _str=s._str; _refcount=s._refcount; ++(*_refcount); } return *this; } ~String() { Release(); } public: void CopyOnWrite() { if(*_refcount>1) { char *tmp=new char[strlen(_str)+1]; strcpy(tmp,_str); --(*_refcount); _str=tmp; _recount=new int(1); } } void Release() { if(--(*_refcount)==0) { delete[] _str; delete _refcount; } } private: char *_str; int *_refcount; }; int main() { String s1("hello"); String s2(s1); s2=s1; return 0; }
以上這種方法,建立物件時需要都需給_refcount建立新的空間,釋放的時候也需釋放兩次,效率比較低,那能不能進行改進呢?
原理圖:
具體程式碼:
#define _CRT_SECURE_NO_WARNINGS 1 //引用計數的寫時拷貝(淺拷貝) #include using namespace std; class String { public: String(const char *str="") :_str(new char[strlen(str)+5]) { _str+=4; strcpy(_str,str); (*(int *)(_str-4))=1; } String(const String& s) :_str(s._str) { GetRefcount()++; } ~String() { Release(); } String& operator=(const String& s) { if(_str!=s._str) { if(--GetRefcount()==0) { Release(); } _str=s._str ; GetRefcount()++; } } void Release() { if(GetRefcount()==1) { delete[] (_str-4); cout<<"delect"<1) { char* tmp=new char[strlen(_str)+5]; tmp+=4; strcpy(tmp,_str); _str=tmp; GetRefcount()=1; } } public : int& GetRefcount() { return (*(int *)(_str-4)); } char* GetStr() { return _str; } char& operator[](size_t pos) { CopyOnWrite(); return _str[pos]; } private: char *_str; }; int main() { String s1("hello"); String s2(s1); String s3=s2; s3[1]='m'; cout<