C++11中的default函數(shù)使用
對(duì)于C++ 11標(biāo)準(zhǔn)中支持的default函數(shù),編譯器會(huì)為其自動(dòng)生成默認(rèn)的函數(shù)定義體,從而獲得更高的代碼執(zhí)行效率,也可免除程序員手動(dòng)定義該函數(shù)的工作量。
C++的類有四類特殊成員函數(shù),它們分別是:
- 默認(rèn)構(gòu)造函數(shù)
- 析構(gòu)函數(shù)
- 拷貝構(gòu)造函數(shù)
- 拷貝賦值運(yùn)算符
這些類的特殊成員函數(shù)負(fù)責(zé)創(chuàng)建、初始化、銷毀,或者拷貝類的對(duì)象,如果程序員沒(méi)有顯式地為一個(gè)類定義某個(gè)特殊成員函數(shù),而又需要用到該特殊成員函數(shù)時(shí),則編譯器會(huì)隱式的為這個(gè)類生成一個(gè)默認(rèn)的特殊成員函數(shù)。例如:
清單 1
class X{ private: int a; }; X x;
在清單 1 中,程序員并沒(méi)有定義類 X 的默認(rèn)構(gòu)造函數(shù),但是在創(chuàng)建類 X 的對(duì)象 x 的時(shí)候,又需要用到類 X 的默認(rèn)構(gòu)造函數(shù),此時(shí),編譯器會(huì)隱式的為類 X 生成一個(gè)默認(rèn)構(gòu)造函數(shù)。該自動(dòng)生成的默認(rèn)構(gòu)造函數(shù)沒(méi)有參數(shù),包含一個(gè)空的函數(shù)體,即 X::X(){ }。雖然自動(dòng)生成的默認(rèn)構(gòu)造函數(shù)僅有一個(gè)空函數(shù)體,但是它仍可用來(lái)成功創(chuàng)建類 X 的對(duì)象 x,清單 1 也可以編譯通過(guò)。
但是,如果程序員為類 X 顯式的自定義了非默認(rèn)構(gòu)造函數(shù),卻沒(méi)有定義默認(rèn)構(gòu)造函數(shù)的時(shí)候,清單 2 將會(huì)出現(xiàn)編譯錯(cuò)誤:
清單 2
class X{ public: X(int i){ a = i; } private: int a; }; X x; // 錯(cuò)誤 , 默認(rèn)構(gòu)造函數(shù) X::X() 不存在
清單 2 編譯出錯(cuò)的原因在于類 X 已經(jīng)有了用戶自定義的構(gòu)造函數(shù),所以編譯器將不再會(huì)為它隱式的生成默認(rèn)構(gòu)造函數(shù)。如果需要用到默認(rèn)構(gòu)造函數(shù)來(lái)創(chuàng)建類的對(duì)象時(shí),程序員必須自己顯式的定義默認(rèn)構(gòu)造函數(shù)。例如:
清單 3
class X{ public: X(){}; // 手動(dòng)定義默認(rèn)構(gòu)造函數(shù) X(int i){ a = i; } private: int a; }; X x; // 正確,默認(rèn)構(gòu)造函數(shù) X::X() 存在
從清單 3 可以看出,原本期望編譯器自動(dòng)生成的默認(rèn)構(gòu)造函數(shù)需要程序員手動(dòng)編寫(xiě)了,即程序員的工作量加大了。此外,手動(dòng)編寫(xiě)的默認(rèn)構(gòu)造函數(shù)的代碼執(zhí)行效率比編譯器自動(dòng)生成的默認(rèn)構(gòu)造函數(shù)低。類的其它幾類特殊成員函數(shù)也和默認(rèn)構(gòu)造函數(shù)一樣,當(dāng)存在用戶自定義的特殊成員函數(shù)時(shí),編譯器將不會(huì)隱式的自動(dòng)生成默認(rèn)特殊成員函數(shù),而需要程序員手動(dòng)編寫(xiě),加大了程序員的工作量。類似的,手動(dòng)編寫(xiě)的特殊成員函數(shù)的代碼執(zhí)行效率比編譯器自動(dòng)生成的特殊成員函數(shù)低。
為了解決如清單 3 所示的兩個(gè)問(wèn)題:
減輕程序員的編程工作量;
- 獲得編譯器自動(dòng)生成的默認(rèn)特殊成員函數(shù)的高的代碼執(zhí)行效率
- C++11 標(biāo)準(zhǔn)引入了一個(gè)新特性:default函數(shù)。程序員只需在函數(shù)聲明后加上=default;,就可將該函數(shù)聲明為 default 函數(shù),編譯器將為顯式聲明的 default 函數(shù)自動(dòng)生成函數(shù)體。例如:
清單 4
class X{ public: X()= default; X(int i){ a = i; } private: int a; }; X x;
在清單 4 中,編譯器會(huì)自動(dòng)生成默認(rèn)構(gòu)造函數(shù) X::X(){},該函數(shù)可以比用戶自己定義的默認(rèn)構(gòu)造函數(shù)獲得更高的代碼效率。
Default 函數(shù)特性僅適用于類的特殊成員函數(shù),且該特殊成員函數(shù)沒(méi)有默認(rèn)參數(shù)。例如:
清單 5
class X { public: int f() = default; // 錯(cuò)誤 , 函數(shù) f() 非類 X 的特殊成員函數(shù) X(int) = default; // 錯(cuò)誤 , 構(gòu)造函數(shù) X(int, int) 非 X 的特殊成員函數(shù) X(int = 1) = default; // 錯(cuò)誤 , 默認(rèn)構(gòu)造函數(shù) X(int=1) 含有默認(rèn)參數(shù) };
Default 函數(shù)既可以在類體里(inline)定義,也可以在類體外(out-of-line)定義。例如:
清單 6
class X{ public: X() = default; //Inline default 默認(rèn)構(gòu)造函數(shù) X(const X&); X& operator = (const X&); ~X() = default; //Inline default 析構(gòu)函數(shù) }; X::X(const X&) = default; //Out-of-line default 拷貝構(gòu)造函數(shù) X& X::operator = (const X&) = default; //Out-of-line default // 拷貝賦值操作符
在 C++ 代碼編譯過(guò)程中,如果程序員沒(méi)有為類 X 定義析構(gòu)函數(shù),但是在銷毀類 X 對(duì)象的時(shí)候又需要調(diào)用類 X 的析構(gòu)函數(shù)時(shí),編譯器會(huì)自動(dòng)隱式的為該類生成一個(gè)析構(gòu)函數(shù)。該自動(dòng)生成的析構(gòu)函數(shù)沒(méi)有參數(shù),包含一個(gè)空的函數(shù)體,即 X::~X(){ }。例如:
清單 7
class X { private: int x; }; class Y: public X { private: int y; }; int main(){ X* x = new Y; delete x; }
在清單 7 中,程序員沒(méi)有為基類 X 和派生類 Y 定義析構(gòu)函數(shù),當(dāng)在主函數(shù)內(nèi) delete 基類指針 x 的時(shí)候,需要調(diào)用基類的析構(gòu)函數(shù)。于是,編譯器會(huì)隱式自動(dòng)的為類 X 生成一個(gè)析構(gòu)函數(shù),從而可以成功的銷毀 x 指向的派生類對(duì)象中的基類子對(duì)象(即 int 型成員變量 x)。
但是,這段代碼存在內(nèi)存泄露的問(wèn)題,當(dāng)利用 delete 語(yǔ)句刪除指向派生類對(duì)象的指針 x 時(shí),系統(tǒng)調(diào)用的是基類的析構(gòu)函數(shù),而非派生類 Y 類的析構(gòu)函數(shù),因此,編譯器無(wú)法析構(gòu)派生類的 int 型成員變量 y。
因此,一般情況下我們需要將基類的析構(gòu)函數(shù)定義為虛函數(shù),當(dāng)利用 delete 語(yǔ)句刪除指向派生類對(duì)象的基類指針時(shí),系統(tǒng)會(huì)調(diào)用相應(yīng)的派生類的析構(gòu)函數(shù)(實(shí)現(xiàn)多態(tài)性),從而避免內(nèi)存泄露。但是編譯器隱式自動(dòng)生成的析構(gòu)函數(shù)都是非虛函數(shù),這就需要由程序員手動(dòng)的為基類 X 定義虛析構(gòu)函數(shù),例如:
清單 8
class X { public: virtual ~X(){}; // 手動(dòng)定義虛析構(gòu)函數(shù) private: int x; }; class Y: public X { private: int y; }; int main(){ X* x = new Y; delete x; }
在清單 8 中,由于程序員手動(dòng)為基類 X 定義了虛析構(gòu)函數(shù),當(dāng)利用 delete 語(yǔ)句刪除指向派生類對(duì)象的基類指針 x 時(shí),系統(tǒng)會(huì)調(diào)用相應(yīng)的派生類 Y 的析構(gòu)函數(shù)(由編譯器隱式自動(dòng)生成)以及基類 X 的析構(gòu)函數(shù),從而將派生類對(duì)象完整的銷毀,可以避免內(nèi)存泄露。
但是,在清單 8 中,程序員需要手動(dòng)的編寫(xiě)基類的虛構(gòu)函數(shù)的定義(哪怕函數(shù)體是空的),增加了程序員的編程工作量。更值得一提的是,手動(dòng)定義的析構(gòu)函數(shù)的代碼執(zhí)行效率要低于編譯器自動(dòng)生成的析構(gòu)函數(shù)。
為了解決上述問(wèn)題,我們可以將基類的虛析構(gòu)函數(shù)聲明為 default 函數(shù),這樣就可以顯式的指定編譯器為該函數(shù)自動(dòng)生成函數(shù)體。例如:
清單 9
class X { public: virtual ~X()= default; // 編譯器自動(dòng)生成 default 函數(shù)定義體 private: int x; }; class Y: public X { private: int y; }; int main(){ X* x = new Y; delete x; }
到此這篇關(guān)于C++11中的default函數(shù)使用的文章就介紹到這了,更多相關(guān)C++11 default函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Qt編寫(xiě)地圖遷徙圖的實(shí)現(xiàn)示例
本文主要介紹了Qt編寫(xiě)地圖遷徙圖的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12C++標(biāo)準(zhǔn)模板庫(kù)vector的常用操作
今天小編就為大家分享一篇關(guān)于C++標(biāo)準(zhǔn)模板庫(kù)vector的常用操作,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12C++ Thread實(shí)現(xiàn)簡(jiǎn)單的socket多線程通信
本文主要介紹了C++ Thread實(shí)現(xiàn)簡(jiǎn)單的socket多線程通信,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07c++統(tǒng)計(jì)文件中字符個(gè)數(shù)代碼匯總
本文給大家匯總介紹了3種使用C++實(shí)現(xiàn)統(tǒng)計(jì)文件中的字符個(gè)數(shù)的方法,非常的簡(jiǎn)單實(shí)用,有需要的小伙伴可以參考下。2015-09-09C++中用指向數(shù)組的指針作函數(shù)參數(shù)
多維數(shù)組名作為函數(shù)參數(shù)傳遞:在二維數(shù)組中,數(shù)組名a是指向首行a[0]的指針,也就是說(shuō)a=&a[0]; a[0]是指向首元素a[0][0]的指針,也就是說(shuō)a[0]=&a[0][0]2013-10-10