c++中深淺拷貝以及寫時拷貝的實現(xiàn)示例代碼
本文主要給大家介紹了關于c++中深淺拷貝及寫時拷貝實現(xiàn)的相關內(nèi)容,分享出來供大家參考學習,下面話不多說,來一起看看詳細的介紹:
一:淺拷貝&深拷貝
淺拷貝:在拷貝構造的時候,直接將原內(nèi)容的地址交給要拷貝的類,兩個類共同指向一片空間。但是存在很大的缺陷:①一旦對s2進行操作,s1的內(nèi)容也會改變;②析構時先析構s2,再析構s1,但是由于s1,s2指向同一片空間,會導致一片空間的二次析構導致出錯。
深拷貝:通過開辟和源空間大小相同的空間并將內(nèi)容拷貝下來再進行操作。不論是否對s2進行操作,都會拷貝一片相同大小的空間以及內(nèi)容下來。
圖示如下:
深拷貝實現(xiàn)如下:
#include <iostream> using namespace std; class String { public: String(char* str = "") :_str(new char[strlen(str)+1]) { strcpy(_str, str); } //傳統(tǒng)寫法,開辟空間 String(const String& s) { _str = new(char[strlen(s._str) + 1]); strcpy(_str, s._str); } //現(xiàn)代寫法,利用構造函數(shù) //String(const String& s) // :_str(NULL) //{ // String tmp(s._str); // swap(_str, tmp._str); //} //****************賦值運算符重載************** //String& operator=(const String& s) //{ // if (this != &s) // { // delete[] _str; // _str = new char[strlen(s._str) + 1]; // strcpy(_str, s._str); // } // return *this; //} //****************賦值運算符重載************** String& operator=(String& s) { swap(_str, s._str); return *this; } //***************析構函數(shù)******************** ~String() { if (_str) { delete[] _str; } } private: char* _str; };
二:寫時拷貝
寫時拷貝:引入一個計數(shù)器,每片不同內(nèi)容的空間上都再由一個計數(shù)器組成,在構造第一個類指向時,計數(shù)器初始化為1,之后每次有新的類也指向同一片空間時,計數(shù)器加價;在析構時判斷該片空間對應計數(shù)器是否為1,為1則執(zhí)行清理工作,大于1則計數(shù)器-1。如果有需要進行增刪等操作時,再拷貝空間完成,有利于提高效率。
寫法一:
#include <iostream> using namespace std; class String { public: String(char* str = "") :_str(new char[strlen(str)]+1) , _refCount(new int(1)) { strcpy(_str, str); } String(const String& str) : _str(str._str) ,_refCount(str._refCount) { (*_refCount)++; } ~String() { release(); } String& operator= (const String& s) { if (_str != s._str) { release(); _refCount = s._refCount; (*_refCount)++; _str = s._str; } return *this; } void release() { if ((*--_refCount) == 0) { delete[] _str; delete _refCount; } } private: char* _str; int* _refCount; };
缺點:每構造一個新類,就會多開四個字節(jié),會導致空間中有許多的內(nèi)存碎片。
第二種:
class String { public: String(char* str = "") :_str(new char[strlen(str)+1+4]) { *(int*)_str = 1; _str += 4; strcpy(_str, str); } String(const String& s) :_str(s._str) { ++GetCount(); } ~String() { release(); } String& operator=(const String& s) { if (this != &s) { realease(); _str = s._str; GetCount()++; } return *this; } void release() { if (--GetCount() == 0) { _str -= 4; delete[] _str; } } int& GetCount() { return *((int*)_str - 1); } private: char* _str; };
注意:由于計數(shù)器存放在了_str首地址-4的地址上,所以在析構時一定要注意全部釋放,避免內(nèi)存泄漏。
圖示如下:
總結
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持
相關文章
詳解如何配置CLion作為Qt5開發(fā)環(huán)境的方法
這篇文章主要介紹了詳解如何配置CLion作為Qt5開發(fā)環(huán)境的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-04-04類成員函數(shù)的重載、覆蓋與隱藏之間的區(qū)別總結
以下是對類成員函數(shù)的重載、覆蓋與隱藏之間的區(qū)別進行了詳細的總結分析,需要的朋友可以過來參考下。希望對大家有所幫助2013-10-10C++中string字符串分割函數(shù)split()的4種實現(xiàn)方法
最近筆試經(jīng)常遇到需要對字符串進行快速分割的情景,下面這篇文章主要給大家介紹了關于C++中string字符串分割函數(shù)split()的4種實現(xiàn)方法,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-06-06