您好,登錄后才能下訂單哦!
了解過C++語言的人,都應該知道,C++語言中的構造函數,析構函數,拷貝構造函數,賦值運算符重載函數,如果不定義,編譯器會自動生成的,當然,生成的只是一些最基本的,在達不到我們要求的條件下,就需要我們自己重新定義這些函數。
我們現在說的講的是深拷貝與淺拷貝,當然討論這個問題的基礎,一般情況下是我們定義的變量是以指針形式出現的,原因就在于,不論賦值還是拷貝,我們要實現兩個指針指向的內容一致,那我得到新的指針和原指針是指向同一塊內存空間還是兩塊內存空間的相同內容。如果是指向同一塊空間,就存在了安全隱患,我們在自己管理空間時,就很有可能對一塊空間進行了多次的釋放,有些編譯器下會報錯,甚至直接奔潰,有些編譯器雖不會拋出異常,但也會對后續的程序造成未知的錯誤。
那么,現在就以String為例,看看如何解決這些問題。
//參數列表中,pstr為char* 類型,s為String類型
//實現方法1:
class String { friend ostream& operator<<(ostream& _out, const String& s); public: String(const char* pstr) :_str(new char[strlen(pstr)+1]) { strcpy(_str,pstr); cout << "構造" << endl;//做標識 } String(const String& s) :_str(new char[strlen(s._str) + 1]) { strcpy(_str,s._str); cout << "拷貝構造"<<endl;//做標識 } String& operator = (const String& s) { if (this == &s)//不給自己賦值,防止對一塊空間進行二次析構 { char* tmp = (new char[strlen(s._str) + 1]); strcpy(tmp, s._str); delete[]_str; _str = tmp; } cout << "賦值重載" << endl;//做標識 return *this; //注意返回值 } ~String() { if (this != NULL) { delete[]_str; _str = NULL; } cout << "析構" <<endl;//做標識 } private: char *_str; }; //輸出運算符重載 ostream& operator<<(ostream& _out,const String& s) { _out << s._str<< endl; return _out; }
//*****************************************************************************************
//String類的實現2
class String { friend ostream& operator<<(ostream& _out, const String& s); public: String(const char* str) :_str(new char[strlen(str)+1])//同上 { strcpy(_str,str); } //拷貝構造 String(const String& s) : _str(NULL) { String tmp(s._str); std::swap(_str,tmp._str); } //賦值運算符重載 //String&operator=(const String& s) //{ // if (this != &s) // { // char* tmp(s._str);//用s._str或者s實例化tmp都可以 // std::swap(_str,tmp); // } // return *this; //} //賦值運算符重載之開辟空間法 String&operator=(const String& s) { if (this != &s) { char* tmp = new char[strlen(s._str) + 1]; strcpy(tmp,s._str); delete[]_str; _str = tmp; } return *this; } //析構 ~String() { if (NULL == _str) { delete[] _str; _str = NULL; } } private: char* _str; }; //輸出運算符重載 ostream& operator<<(ostream& _out,const String& s) { _out << s._str<< endl; return _out; }
// String類的實現3------>淺拷貝實現防止內存的多次釋放
class String { friend ostream& operator<<(ostream& _out, const String& s); public: String(const char* pdata) :_str(new char[strlen(pdata)+1]) , _count(new int) { strcpy(_str,pdata); *_count = 1; } String(const String& s) :_str(s._str) , _count(s._count) { _count++; } String& operator=(const String& s) { if (this != &s) { if (--(*_count) == 0) { delete[]_str; delete _count; } _count = s._count; _str = s._str; _count++; } return* this; } ~String() { if (--(*_count) == 0) { delete[] _str; delete _count; } } private: char* _str; int* _count; }; //輸出運算符重載 ostream& operator<<(ostream& _out,const String& s) { _out << s._str<< endl; return _out; }
//*****************************************************************************************
友元函數受第一參數的限制,只能采用類外定義,引入友元
方法三,關于引入計數器,在面試過程中,這是最不推薦的方法,HR往往更傾向于讓你寫出深拷貝的方法。
深拷貝與淺拷貝是面試過程中經常出現的題目,弄清楚這類問題是非常必要的
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。