淺拷貝:編譯器只是直接將指標的值拷貝過來,結果多個物件共用了一塊記憶體,當乙個物件呼叫了析構函式將這塊記憶體釋放掉之後,另一些物件不知道這塊空間已經還給了系統,再次呼叫析構函式進行釋放時發現已經釋放了,就會造成程式崩潰。在類的成員中有指標型別的成員變數的時候,必須對其寫出顯式的拷貝建構函式和賦值運算子過載函式,否則,預設的拷貝建構函式和賦值運算子過載函式只會對該指標進行淺拷貝(即直接將指標的值拷貝過來),導致多個物件的指標變數實際上指的是同一塊空間,會引發一系列的問題甚至是程式崩潰class string
~string()
private:
char* mptr;
};int main()
深拷貝:因為淺拷貝會引發種種的問題,所以這裡就引入了深拷貝。深拷貝會在構造其餘物件的時候,拷貝一塊和被拷貝物件一樣大的空間,並將空間內的內容拷貝過來。這樣不同的物件就會指向不同的資料塊。在涉及到類中有指標型別的變數時,尤其是要對該類進行相關拷貝的操作時,一定要顯式的定義乙個拷貝建構函式或是賦值運算子過載,進行深拷貝,不能用淺拷貝!!!class string
;string::string(const char *str)
else
}string::~string(void)
string::string(const mystring &other)
string & string::operator = (const mystring &other)
int main()
寫時拷貝 : 寫時拷貝,在複製乙個物件的時候並不是真正的把原先的物件複製到記憶體的另外乙個位置上,而是在新物件的記憶體對映表中設定乙個指標,指向源物件的位置,並把那塊記憶體的引用計數字加1。這樣,在對新的物件執行讀操作的時候,記憶體資料不發生任何變動,直接執行讀操作;而在對新的物件執行寫操作時,將真正的物件複製到新的記憶體位址中,並修改新物件的記憶體對映表指向這個新的位置,並在新的記憶體位置上執行寫操作。原理:採用引用計數的機制。當乙個string物件str1構造時,string的建構函式會根據傳入的引數在堆空間上分配記憶體,當有其他物件通過str1進行拷貝構造的時候,str1的引用計數會+1(即當有其他類需要這塊記憶體的時候,引用計數+1)。當有物件析構時,這個引用計數會-1。直到最後乙個物件析構時,引用計數為0,此時程式才會真正釋放這塊記憶體(前面的析構並沒有釋放該記憶體,而是讓引用計數-1)。
class string
string(const string& rhs) //拷貝構造,淺拷貝,加引用計數
string& operator=(const string& rhs) //賦值運算子的過載
mptr = null;
mptr = rhs.mptr;
getref()++;
}return *this;
}~string() //析構,減引用計數,當等於零時釋放記憶體
mptr = null;
}char& operator(int index) //寫操作,舊的記憶體塊,引用計數-1,開闢新位址,賦值,引用計數為1,
return mptr[index];
}/* 』<<『運算子的過載:
friend ostream& operator <<(ostream& _cout,const string& s);
ostream& operator<<(ostream& _cout, const string& s)
*/private:
int& getref() //獲取引用計數
char* mptr; //指標
};int main()
C 淺拷貝 深拷貝 寫時拷貝
不是拷貝了基本型別的資料,而引用型別資料,複製後也是會發生引用,我們把這種拷貝叫做淺拷貝。換句話說,淺複製僅僅是指向被複製的記憶體位址,如果原位址中物件被改變了,那麼淺複製出來的物件也會相應改變。int main 在計算機中開闢了一塊新的記憶體位址用於存放複製的物件。上述 中p1和p2指向的同一塊記...
淺拷貝,深拷貝,寫時拷貝
淺拷貝 拷貝構造時複製指標僅僅是對指標的值拷貝,而不開闢新的空間這樣就會造成在析構的時候。會對同一塊記憶體釋放兩次。深拷貝 拷貝構造時會開闢新的記憶體,並把記憶體中的值進行拷貝 寫時拷貝 就是當你在讀取一片空間時,系統並不會為你開闢乙個一模一樣的空間給你 只有在當你真正修改的時候,才會開闢一片空間給...
深拷貝 淺拷貝 寫時拷貝
在拷貝構造的時候,直接將原內容的位址交給要拷貝的類,兩個類共同指向一塊記憶體。缺陷 1 一旦對str2進行操作,str1的內容也會改變 2 析構時先析構str2,再析構str1,但是由於str1,str2指向同一塊記憶體空間,因此會導致對一塊記憶體進行兩次析構而出現錯誤 通過開闢和源空間大小相同的記...