C++深淺拷貝和寫時(shí)拷貝圖文詳解
前言
之前我們在淺談6個(gè)成員函數(shù)中有提到深淺拷貝的問題,現(xiàn)在再回首掏一把。
一、深淺拷貝哪家強(qiáng)?
先給出代碼理一理
#define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> #include<assert.h> using namespace std; class String { friend ostream& operator<<(ostream &out, const String &s); public: String(const char* str = "") { m_data = new char[strlen(str) + 1]; strcpy(m_data, str); } //String(const String& s)//qian拷貝 //{ // m_data = s.m_data; //} String(const String& s)//深拷貝 { m_data = new char[strlen(s.m_data) + 1]; strcpy(m_data, s.m_data); } String& operator=(const String& s) { if (this != &s) { delete[]m_data; m_data = new char[strlen(s.m_data) + 1]; strcpy(m_data, s.m_data); } return *this; } ~String() { delete[]m_data; m_data = nullptr; } private: char* m_data; }; ostream& operator<<(ostream &out, const String &s) { out << s.m_data; return out; } void main() { String s1("abc"); String s2 = s1; cout << "s1 = " << s1 << endl; cout << "s2 = " << s2 << endl; }
而我們之前所說的淺拷貝崩潰是因?yàn)閐oublefree的問題,因此我們可以定義一個(gè)引用計(jì)數(shù)器,來記錄當(dāng)前使用該值的對象數(shù),如果數(shù)目大于1,則不釋放內(nèi)存。
class String { friend ostream& operator<<(ostream &out, const String &s); public: String(const char* str = "") { m_data = new char[strlen(str) + 1]; strcpy(m_data, str); m_count++; } String(const String& s)//淺拷貝 { m_data = s.m_data; m_count++; } String& operator=(const String& s) { if (this != &s) { m_data = s.m_data; m_count++; } return *this; } ~String()//淺賦值 { if (--m_count == 0) { delete[]m_data; m_data = nullptr; } } private: char* m_data; static int m_count;//引用計(jì)數(shù)器 }; int String::m_count = 0; ostream& operator<<(ostream &out, const String &s) { out << s.m_data; return out; } void main() { String s1("abc"); String s2 = s1; String s3; s3 = s2; cout << "s1 = " << s1 << endl; cout << "s2 = " << s2 << endl; cout << "s3 = " << s3 << endl; }
可以看出,三個(gè)對象的m_data共享同一塊內(nèi)存空間,節(jié)省了資源;
但是暴露出了很多的問題:站在對象的角度,其中一個(gè)對象改變m_data其他的對象也會隨之改變;其二若s3使用其他字符串初始化,但計(jì)數(shù)器還是三者共享。
倘若我們使用深拷貝方法,就不會出現(xiàn)這種問題。如果可以在不改變m_data前使用淺拷貝,在改變時(shí)使用深拷貝,暨同時(shí)實(shí)現(xiàn)深淺拷貝,那么就兩全其美。
二、寫時(shí)拷貝
通過對上面問題的分析,我們需要實(shí)現(xiàn):引用計(jì)數(shù)器管理不同的空間。
class String_rep { public: String_rep(const char* str = "") :m_count(0) { m_data = new char[strlen(str) + 1]; strcpy(m_data, str); cout << "creat" << endl; } String_rep(const String_rep &rep) :m_count(0) { m_data = rep.m_data; increment(); } String_rep & operator=(const String_rep &rep) { if (this != &rep) { m_data = rep.m_data; increment(); } return *this; } public: void increment() {m_count++;} void decrement() {m_count--;} private: char* m_data; int m_count; }; class String { public: String(const char* str = "") :pn(new String_rep(str)) { pn->increment(); } ~String() { cout << "Free" << endl; } private: String_rep *pn; }; void main() { String s1("abc"); }
拷貝構(gòu)造:s1和s2管理同一塊空間
定義s3,和s1、s2沒有關(guān)聯(lián);
我們再完全理一遍:
此時(shí)已經(jīng)解決我們之前提到過的第二個(gè)問題。
再來看第一個(gè)問題:
s1的改變影響了s2;
寫時(shí)拷貝:需要改變的時(shí)候深拷貝。
void to_upper() { String_rep *new_pn = new String_rep(pn->Getdata());//創(chuàng)建新空間 pn->decrement();//原空間計(jì)數(shù)器減一 pn = new_pn;//需要更改的對象的pn指向新空間 pn->increment();//新空間的計(jì)數(shù)器加一 char* p = pn->Getdata(); while (*p != '\0') { if (*p >= 'a' && *p <= 'z') *p -= 32; p++; }
總結(jié)
到此這篇關(guān)于C++深淺拷貝和寫時(shí)拷貝的文章就介紹到這了,更多相關(guān)C++深淺拷貝 寫時(shí)拷貝內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C/C++實(shí)現(xiàn)圖形學(xué)掃描線填充算法
這篇文章主要介紹了C/C++實(shí)現(xiàn)圖形學(xué)掃描線填充算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04C語言實(shí)現(xiàn)超市信息管理系統(tǒng)課程設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)超市信息管理系統(tǒng)課程設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03C++實(shí)現(xiàn)帶頭雙向循環(huán)鏈表的示例詳解
這篇文章主要介紹了如何利用C++實(shí)現(xiàn)帶頭雙向循環(huán)鏈表,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-12-12C++中使用哈希表(unordered_map)的一些常用操作方法
C++標(biāo)準(zhǔn)庫中使用的unordered_map底層實(shí)現(xiàn)是哈希表,下面這篇文章主要給大家介紹了關(guān)于C++中使用哈希表(unordered_map)的一些常用操作方法,需要的朋友可以參考下2022-03-03