C++編程語(yǔ)言中賦值運(yùn)算符重載函數(shù)(operator=)的使用
本文主要介紹 C++ 編程語(yǔ)言中賦值運(yùn)算符重載函數(shù)(operator=)的相關(guān)知識(shí),同時(shí)通過(guò)示例代碼介紹賦值運(yùn)算符重載函數(shù)的使用方法。
1 概述
1.1 Why
首先介紹為什么要對(duì)賦值運(yùn)算符“=”進(jìn)行重載。某些情況下,當(dāng)我們編寫(xiě)一個(gè)類(lèi)的時(shí)候,并不需要為該類(lèi)重載“=”運(yùn)算符,因?yàn)榫幾g系統(tǒng)為每個(gè)類(lèi)提供了默認(rèn)的賦值運(yùn)算符“=”,使用這個(gè)默認(rèn)的賦值運(yùn)算符操作類(lèi)對(duì)象時(shí),該運(yùn)算符會(huì)把這個(gè)類(lèi)的所有數(shù)據(jù)成員都進(jìn)行一次賦值操作。例如有如下類(lèi):
class A { public: int a; int b; int c; };
對(duì)這個(gè)類(lèi)的對(duì)象進(jìn)行賦值時(shí),使用默認(rèn)的賦值運(yùn)算符是沒(méi)有問(wèn)題的。
示例代碼內(nèi)容如下:
#include <iostream> using namespace std; class ClassA { public: int a; int b; int c; }; int main() { ClassA obj1; obj1.a = 1; obj1.b = 2; obj1.c = 3; ClassA obj2; obj2 = obj1; cout << "obj2.a is: " << obj2.a << endl; return 0; }
編譯并執(zhí)行上述代碼,結(jié)果如下:
通過(guò)上述結(jié)果能夠知道:通過(guò)使用系統(tǒng)默認(rèn)的賦值運(yùn)算符“=”,可以讓對(duì)象 obj2 中的所有數(shù)據(jù)成員的值與對(duì)象 obj1 相同。這種情況下,編譯系統(tǒng)提供的默認(rèn)賦值運(yùn)算符可以正常使用。
但是,在下面的示例中,使用編譯系統(tǒng)提供的默認(rèn)賦值運(yùn)算符,就會(huì)出現(xiàn)問(wèn)題了。
示例代碼內(nèi)容如下:
#include <iostream> #include <string.h> using namespace std; class ClassA { public: ClassA() { } ClassA(const char* pszInputStr) { pszTestStr = new char[strlen(pszInputStr) + 1]; strncpy(pszTestStr, pszInputStr, strlen(pszInputStr) + 1); } virtual ~ClassA() { delete pszTestStr; } public: char* pszTestStr; }; int main() { ClassA obj1("liitdar"); ClassA obj2; obj2 = obj1; cout << "obj2.pszTestStr is: " << obj2.pszTestStr << endl; cout << "addr(obj1.pszTestStr) is: " << &obj1.pszTestStr << endl; cout << "addr(obj2.pszTestStr) is: " << &obj2.pszTestStr << endl; return 0; }
編譯并運(yùn)行上述代碼,結(jié)果如下:
上述錯(cuò)誤信息表明:當(dāng)對(duì)象 obj1 和 obj2 進(jìn)行析構(gòu)時(shí),由于重復(fù)釋放了同一塊內(nèi)存空間,導(dǎo)致程序崩潰報(bào)錯(cuò)。在這種情況下,就需要我們重載賦值運(yùn)算符“=”了。
2 示例代碼
2.1 示例代碼1
我們修改一下前面出錯(cuò)的示例代碼,編寫(xiě)一個(gè)包含賦值運(yùn)算符重載函數(shù)的類(lèi),修改后的代碼內(nèi)容如下:
#include <iostream> #include <string.h> using namespace std; class ClassA { public: ClassA() { } ClassA(const char* pszInputStr) { pszTestStr = new char[strlen(pszInputStr) + 1]; strncpy(pszTestStr, pszInputStr, strlen(pszInputStr) + 1); } virtual ~ClassA() { delete pszTestStr; } // 賦值運(yùn)算符重載函數(shù) ClassA& operator=(const ClassA& cls) { // 避免自賦值 if (this != &cls) { // 避免內(nèi)存泄露 if (pszTestStr != NULL) { delete pszTestStr; pszTestStr = NULL; } pszTestStr = new char[strlen(cls.pszTestStr) + 1]; strncpy(pszTestStr, cls.pszTestStr, strlen(cls.pszTestStr) + 1); } return *this; } public: char* pszTestStr; }; int main() { ClassA obj1("liitdar"); ClassA obj2; obj2 = obj1; cout << "obj2.pszTestStr is: " << obj2.pszTestStr << endl; cout << "addr(obj1.pszTestStr) is: " << &obj1.pszTestStr << endl; cout << "addr(obj2.pszTestStr) is: " << &obj2.pszTestStr << endl; return 0; }
編譯并運(yùn)行上述代碼,結(jié)果如下:
通過(guò)上述結(jié)果能夠看到,利用賦值運(yùn)算符重載函數(shù),解決了對(duì)象賦值時(shí),析構(gòu)函數(shù)多次釋放同一塊內(nèi)存空間的問(wèn)題。
對(duì)于上述代碼,有以下幾點(diǎn)需要說(shuō)明:
當(dāng)為一個(gè)類(lèi)的對(duì)象賦值(可以用本類(lèi)對(duì)象為其賦值,也可以用其它類(lèi)型的值為其賦值)時(shí),該對(duì)象(如本例的 obj2)會(huì)調(diào)用該類(lèi)的賦值運(yùn)算符重載函數(shù),進(jìn)行具體的賦值操作。如上述代碼中的“obj2 = obj1;”語(yǔ)句,用 obj1 為 obj2 賦值,則會(huì)由 obj2 調(diào)用 ClassA 類(lèi)的賦值運(yùn)算符重載函數(shù);
下方語(yǔ)句和語(yǔ)句“ClassA obj2 = obj1;”在調(diào)用函數(shù)上是有區(qū)別的:前者第一句是對(duì)象 obj2 的聲明及定義,調(diào)用類(lèi) ClassA 的無(wú)參構(gòu)造函數(shù),所以“obj2 = obj1;”一句是在對(duì)象 obj2 已經(jīng)存在的情況下,用 obj1 來(lái)為 obj2 賦值,調(diào)用的是賦值運(yùn)算符重載函數(shù);而后者,是用 obj1 來(lái)初始化 obj2,調(diào)用的是拷貝構(gòu)造函數(shù)??截悩?gòu)造函數(shù)的語(yǔ)句樣式為“ClassA(const ClassA& cls)”,關(guān)于拷貝構(gòu)造函數(shù)的詳細(xì)內(nèi)容,請(qǐng)參考相關(guān)內(nèi)容,此處不展開(kāi)介紹;
ClassA obj2; obj2 = obj1;
當(dāng)程序沒(méi)有顯式地提供一個(gè)以“本類(lèi)或本類(lèi)的引用”為參數(shù)的賦值運(yùn)算符重載函數(shù)時(shí),編譯器會(huì)自動(dòng)生成一個(gè)默認(rèn)的賦值運(yùn)算符重載函數(shù)(即默認(rèn)賦值運(yùn)算符)。
2.2 示例代碼2
示例代碼內(nèi)容如下:
#include<iostream> #include<string> using namespace std; class Data { private: int data; public: // 構(gòu)造函數(shù) Data() { }; // 構(gòu)造函數(shù) Data(int _data):data(_data) { cout << "This is constructor" << endl; } // 賦值運(yùn)算符重載函數(shù) Data& operator=(const int _data) { cout << "This is operator=(int _data)" << endl; data = _data; return *this; } }; int main() { // 調(diào)用構(gòu)造函數(shù) Data data1(1); Data data2, data3; // 調(diào)用賦值運(yùn)算符重載函數(shù) data2 = 1; // 調(diào)用默認(rèn)的賦值運(yùn)算符重載函數(shù) data3 = data2; return 0; }
編譯并執(zhí)行上述代碼,結(jié)果如下:
上述結(jié)果表明:“data2 = 1;”語(yǔ)句調(diào)用了我們提供的以 int 型參數(shù)(而非本類(lèi)或本類(lèi)的引用)為形參的賦值運(yùn)算符重載函數(shù);而“data3 = data2;”的成功執(zhí)行,說(shuō)明該語(yǔ)句調(diào)用了編譯器提供的默認(rèn)的賦值運(yùn)算符重載函數(shù)。
如果將上述代碼中賦值運(yùn)算符重載函數(shù)去掉,重新編譯執(zhí)行,結(jié)果如下:
上述結(jié)果說(shuō)明,當(dāng)用一個(gè)非類(lèi) A 的值(如上面的 int 類(lèi)型值)為類(lèi) A 的對(duì)象賦值時(shí):
- 如果檢測(cè)到構(gòu)造函數(shù)和賦值運(yùn)算符重載函數(shù)同時(shí)存在,則會(huì)優(yōu)先調(diào)用賦值運(yùn)算符重載函數(shù);
- 如果只檢測(cè)到構(gòu)造函數(shù),就會(huì)調(diào)用構(gòu)造函數(shù)。
3 總結(jié)
綜合本文內(nèi)容,可以知道針對(duì)以下情況,需要顯式地提供賦值運(yùn)算符重載函數(shù)(即自定義賦值運(yùn)算符重載函數(shù)):
- 用非類(lèi) A 類(lèi)型的值為類(lèi) A 的對(duì)象賦值時(shí)(當(dāng)然,這種情況下我們也可以不提供相應(yīng)的賦值運(yùn)算符重載函數(shù),而只提供相應(yīng)的構(gòu)造函數(shù),如更改后的示例代碼2);
- 用類(lèi) A 類(lèi)型的值為類(lèi) A 的對(duì)象賦值,且類(lèi) A 的數(shù)據(jù)成員中含有指針的情況下,必須顯式提供賦值運(yùn)算符重載函數(shù)(如示例代碼1)。
到此這篇關(guān)于C++編程語(yǔ)言中賦值運(yùn)算符重載函數(shù)(operator=)介紹的文章就介紹到這了,更多相關(guān)C++ 賦值運(yùn)算符重載函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言的sleep、usleep、nanosleep等休眠函數(shù)的使用
本文主要介紹了C語(yǔ)言的sleep、usleep、nanosleep等休眠函數(shù)的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03opencv利用鼠標(biāo)滑動(dòng)畫(huà)出多彩的形狀
這篇文章主要為大家詳細(xì)介紹了opencv利用鼠標(biāo)滑動(dòng)畫(huà)出多彩的形狀,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07實(shí)例講解C++編程中的虛函數(shù)與虛基類(lèi)
這篇文章主要介紹了C++編程中的虛函數(shù)與虛基類(lèi)的實(shí)例講解,虛函數(shù)與虛基類(lèi)的使用是C++入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2016-02-02