C++構(gòu)造函數(shù)的一些注意事項(xiàng)總結(jié)
1、匿名對(duì)象
首先應(yīng)該明確匿名對(duì)象,匿名對(duì)象是之沒(méi)有對(duì)象名,調(diào)用完構(gòu)造函數(shù)后即析構(gòu)的對(duì)象。下面通過(guò)代碼捕捉類(lèi)的構(gòu)造函數(shù)和析構(gòu)函數(shù),以進(jìn)行說(shuō)明:
#include <iostream> using namespace std; class Solution{ public: Solution(int a, int b):m_num1(a), m_num2(b) { cout << "有參構(gòu)造函數(shù)的調(diào)用" << endl; }; Solution(const Solution& s):m_num1(s.m_num1), m_num2(s.m_num2){ cout << "拷貝構(gòu)造函數(shù)的調(diào)用" << endl; } ~Solution(){ cout << "析構(gòu)函數(shù)的調(diào)用" << endl; } private: int m_num1; int m_num2; }; int main() { Solution(8,9); // Solution(8,9) 匿名對(duì)象 system("pause"); return 0; }
代碼運(yùn)行結(jié)果為:
通過(guò)代碼運(yùn)行結(jié)果可以看到,創(chuàng)建匿名對(duì)象的時(shí)候,調(diào)用了類(lèi)的構(gòu)造函數(shù),隨后立即調(diào)用了析構(gòu)函數(shù)。我們可以直接利用匿名對(duì)象進(jìn)行初始化類(lèi)的成員的初始化,代碼如下:
#include <iostream> using namespace std; class Solution{ public: Solution(int a, int b):m_num1(a), m_num2(b) { cout << "有參構(gòu)造函數(shù)的調(diào)用" << endl; }; Solution(const Solution& s):m_num1(s.m_num1), m_num2(s.m_num2){ cout << "拷貝構(gòu)造函數(shù)的調(diào)用" << endl; } ~Solution(){ cout << "析構(gòu)函數(shù)的調(diào)用" << endl; } int m_num1; int m_num2; }; int main() { Solution s1(Solution(8,9)); // Solution s1 = Solution(8,9); //顯式 Solution(8,9) 匿名對(duì)象初始化類(lèi)成員 // Solution s1 = {8,9}; //{8,9}等價(jià)于Solution(8,9) cout << "s1.m_num1 = " << s1.m_num1 << endl; cout << "s1.m_num2 = " << s1.m_num2 << endl; system("pause"); return 0; }
運(yùn)行結(jié)果如下:
代碼調(diào)用了一次構(gòu)造函數(shù),可見(jiàn)匿名對(duì)象可以初始化類(lèi)成員,就是將匿名對(duì)象轉(zhuǎn)化成了s1對(duì)象,這里需要與拷貝構(gòu)造函數(shù)區(qū)分開(kāi):
#include <iostream> using namespace std; class Solution{ public: Solution(int a, int b):m_num1(a), m_num2(b) { cout << "有參構(gòu)造函數(shù)的調(diào)用" << endl; }; Solution(const Solution& s):m_num1(s.m_num1), m_num2(s.m_num2){ cout << "拷貝構(gòu)造函數(shù)的調(diào)用" << endl; } ~Solution(){ cout << "析構(gòu)函數(shù)的調(diào)用" << endl; } int m_num1; int m_num2; }; int main() { Solution s1(10,11); Solution s2(s1); cout << "s2.m_num1 = " << s2.m_num1 << endl; cout << "s2.m_num2 = " << s2.m_num2 << endl; system("pause"); return 0; }
代碼運(yùn)行結(jié)果為:
對(duì)比以上兩個(gè)代碼可以發(fā)現(xiàn),通過(guò)匿名對(duì)象初始化類(lèi)成員并不是拷貝構(gòu)造,只是一種替換,通過(guò)匿名對(duì)象初始化類(lèi)成員并不會(huì)調(diào)用拷貝構(gòu)造函數(shù)。
2、拷貝構(gòu)造函數(shù)的調(diào)用時(shí)機(jī)
今年秋招筆試題最?lèi)?ài)考查構(gòu)造函數(shù)的調(diào)用時(shí)機(jī),通常會(huì)結(jié)合繼承和多態(tài)來(lái)考察,這里先說(shuō)明一下拷貝構(gòu)造函數(shù)的調(diào)用時(shí)機(jī),后面再詳細(xì)說(shuō)明帶繼承和多態(tài)的構(gòu)造函數(shù)調(diào)用時(shí)機(jī)。
一、使用一個(gè)已經(jīng)創(chuàng)建的對(duì)象來(lái)初始化一個(gè)新對(duì)象,如上面的代碼,創(chuàng)建對(duì)象s1的時(shí)候調(diào)用了有參構(gòu)造函數(shù),通過(guò)s1來(lái)初始化s2的時(shí)候調(diào)用了拷貝構(gòu)造。
二、函數(shù)的參數(shù)是需要值傳遞的對(duì)象的時(shí)候
三、函數(shù)返回對(duì)象的時(shí)候
下面通過(guò)代碼驗(yàn)證,當(dāng)函數(shù)的參數(shù)是一個(gè)需要值傳遞的對(duì)象的情況:
#include <iostream> using namespace std; class Solution{ public: Solution(int a, int b):m_num1(a), m_num2(b) { cout << "有參構(gòu)造函數(shù)的調(diào)用" << endl; }; Solution(const Solution& s):m_num1(s.m_num1), m_num2(s.m_num2){ cout << "拷貝構(gòu)造函數(shù)的調(diào)用" << endl; } ~Solution(){ cout << "析構(gòu)函數(shù)的調(diào)用" << endl; } public: int m_num1; int m_num2; }; void showClassNum(Solution s) { cout << s.m_num1 << endl; cout << s.m_num2 << endl; } int main() { Solution s1(10,11); showClassNum(s1); system("pause"); return 0; }
代碼運(yùn)行結(jié)果為:
通過(guò)代碼運(yùn)行結(jié)果可以看到,s1對(duì)象調(diào)用了有參構(gòu)造函數(shù),當(dāng)把s1傳給函數(shù)的參數(shù)s的時(shí)候調(diào)用了拷貝構(gòu)造函數(shù),函數(shù)執(zhí)行完調(diào)用了s對(duì)象的析構(gòu)函數(shù)。
當(dāng)函數(shù)的返回值是一個(gè)對(duì)象的時(shí)候,也會(huì)調(diào)用拷貝構(gòu)造函數(shù):
#include <iostream> using namespace std; class Solution{ public: Solution(int a, int b):m_num1(a), m_num2(b) { cout << "有參構(gòu)造函數(shù)的調(diào)用" << endl; }; Solution(const Solution& s):m_num1(s.m_num1), m_num2(s.m_num2){ cout << "拷貝構(gòu)造函數(shù)的調(diào)用" << endl; } ~Solution(){ cout << "析構(gòu)函數(shù)的調(diào)用" << endl; } void changeNum(int a, int b) { m_num1 = a; m_num2 = b; } void showNum() { cout << "m_num1 = " << m_num1 << endl; cout << "m_num2 = " << m_num2 << endl; } public: int m_num1; int m_num2; }; Solution clearClassNum(Solution s) { s.changeNum(0,0); return s; } int main() { Solution s1 (10,10); s1 = clearClassNum (s1); s1.showNum(); system("pause"); return 0; }
代碼運(yùn)行結(jié)果為:
從代碼運(yùn)行結(jié)果可以看出來(lái),函數(shù)傳參的時(shí)候調(diào)用了拷貝構(gòu)造,然后函數(shù)返回一個(gè)對(duì)象的時(shí)候的也調(diào)用了拷貝構(gòu)造。
需要注意的是,函數(shù)要返回對(duì)象的時(shí)候,不要使用引用的方式返回,因?yàn)楹瘮?shù)的內(nèi)的變量存放在堆棧區(qū),在函數(shù)執(zhí)行完畢后就會(huì)釋放這塊內(nèi)存,引用就會(huì)出現(xiàn)問(wèn)題。
3、深拷貝和淺拷貝
面試的時(shí)候比較喜歡問(wèn)的問(wèn)題,首先淺拷貝就是我們常用的拷貝,實(shí)現(xiàn)了對(duì)象成員的拷貝,深拷貝就是在堆區(qū)申請(qǐng)空間,然后再進(jìn)行拷貝操作,淺拷貝可以由編譯器完成,但是深拷貝需要我們自己完成,就是有在堆區(qū)開(kāi)辟的內(nèi)存,就一定要自己提供拷貝構(gòu)造函數(shù),防止淺拷貝帶來(lái)的重復(fù)內(nèi)存釋放問(wèn)題。代碼驗(yàn)證如下:
#include <iostream> using namespace std; class Solution{ public: Solution(int a, int b):m_num1(a), pm_num2(new int(b)) { cout << "有參構(gòu)造函數(shù)的調(diào)用" << endl; }; //如果不利用深拷貝在堆區(qū)創(chuàng)建新內(nèi)存,會(huì)導(dǎo)致淺拷貝帶來(lái)的重復(fù)釋放堆區(qū)問(wèn)題,導(dǎo)致程序出錯(cuò) Solution(const Solution& s):m_num1(s.m_num1), pm_num2(new int(*s.pm_num2)) { cout << "拷貝構(gòu)造函數(shù)的調(diào)用" << endl; } ~Solution(){ cout << "析構(gòu)函數(shù)的調(diào)用,釋放堆區(qū)申請(qǐng)的內(nèi)存" << endl; if (pm_num2 != nullptr) { delete pm_num2; } } void changeNum(int a, int b) { m_num1 = a; *pm_num2 = b; } void showNum() { cout << "m_num1 = " << m_num1 << endl; cout << "m_num2 = " << *pm_num2 << endl; } public: int m_num1; int* pm_num2; }; void func() { Solution s1 (10,10); Solution s2(s1); s2.showNum(); } int main() { func(); system("pause"); return 0; }
代碼運(yùn)行結(jié)果為:
總結(jié)
到此這篇關(guān)于C++構(gòu)造函數(shù)注意事項(xiàng)的文章就介紹到這了,更多相關(guān)C++構(gòu)造函數(shù)注意事項(xiàng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Qt實(shí)現(xiàn)簡(jiǎn)單TCP服務(wù)器
這篇文章主要為大家詳細(xì)介紹了Qt實(shí)現(xiàn)簡(jiǎn)單TCP服務(wù)器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08用C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單掃雷游戲
這篇文章主要為大家詳細(xì)介紹了用C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單掃雷游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07C語(yǔ)言中基礎(chǔ)小問(wèn)題詳細(xì)介紹
這篇文章詳細(xì)介紹了C語(yǔ)言中基礎(chǔ)小問(wèn)題,有需要的朋友可以參考一下2013-10-10VC++?2019?"const?char*"類(lèi)型的實(shí)參與"LPCTSTR"
這篇文章主要給大家介紹了關(guān)于VC++?2019?"const?char*"類(lèi)型的實(shí)參與"LPCTSTR"類(lèi)型的形參不兼容的解決方法,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-03-03解析wprintf 中使用%I64d格式化輸出LONGLONG的詳細(xì)介紹
本篇文章是對(duì)wprintf 中使用%I64d格式化輸出LONGLONG進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05Qt5.14.2使用虛擬鍵盤(pán)的關(guān)鍵代碼
對(duì)于Qwidget程序,使用qtvirtualkeyboard彈出鍵盤(pán)之后,鍵盤(pán)會(huì)浮于表面。使用VirtualkeyboardPushView模塊,自動(dòng)根據(jù)情況把輸入視圖往上面推移,這篇文章主要介紹了Qt5.14.2使用虛擬鍵盤(pán)的關(guān)鍵代碼,需要的朋友可以參考下2022-09-09