編譯器會(huì)為class和struct(實(shí)際上兩者在C++中是一回事)自動(dòng)生成構(gòu)造函數(shù)、賦值操作符函數(shù)和析構(gòu)函數(shù)。如果不是這樣,那么開(kāi)發(fā)者就必須自己寫(xiě)一些枯燥冗余的代碼。然而編譯器并不總是生成這些默認(rèn)代碼,當(dāng)它覺(jué)得它無(wú)法生成正確的代碼時(shí),它就會(huì)拒絕生成默認(rèn)代碼。在以下幾種情況中,編譯器會(huì)認(rèn)為它無(wú)法生成正確的代碼:
-
當(dāng)開(kāi)發(fā)者自己定義了構(gòu)造函數(shù)時(shí)
編譯器會(huì)認(rèn)為開(kāi)發(fā)者想要自己定義默認(rèn)構(gòu)造函數(shù)(即無(wú)參數(shù)的構(gòu)造函數(shù)),它無(wú)法猜測(cè)開(kāi)發(fā)者的想法,因此不會(huì)再自動(dòng)生成默認(rèn)構(gòu)造函數(shù)。
-
當(dāng)開(kāi)發(fā)者自己定義了移動(dòng)構(gòu)造函數(shù)時(shí)
編譯器認(rèn)為開(kāi)發(fā)者可能希望僅使用移動(dòng)語(yǔ)義而禁止拷貝,所以拷貝構(gòu)造和拷貝賦值都不再自動(dòng)生成。移動(dòng)賦值也不會(huì)自動(dòng)生成,而是交給開(kāi)發(fā)者自己來(lái)定義,因?yàn)殚_(kāi)發(fā)者已經(jīng)在定義移動(dòng)語(yǔ)義了。
-
當(dāng)開(kāi)發(fā)者自己定義了移動(dòng)賦值操作函數(shù)時(shí)
同上原因,拷貝構(gòu)造和拷貝賦值不再默認(rèn)生成。同樣的原因,移動(dòng)構(gòu)造函數(shù)也不會(huì)自動(dòng)生成。
-
當(dāng)開(kāi)發(fā)者自己定義了拷貝構(gòu)造函數(shù)
編譯器認(rèn)為開(kāi)發(fā)者已經(jīng)自己定義了拷貝語(yǔ)義,無(wú)法保證能自動(dòng)生成正確的移動(dòng)語(yǔ)義的代碼,所以不再自動(dòng)生成此類代碼。C++11標(biāo)準(zhǔn)規(guī)定也不要自動(dòng)生成拷貝賦值操作符函數(shù)代碼,因?yàn)橛脩艚庸芰丝截愓Z(yǔ)義的定義,但是Visual Studio仍然會(huì)生成拷貝賦值操作符函數(shù)代碼。
-
當(dāng)開(kāi)發(fā)者自己定義了拷貝賦值操作函數(shù)時(shí)
同上原因,不再生成移動(dòng)語(yǔ)義的代碼。C++11標(biāo)準(zhǔn)規(guī)定也不要自動(dòng)生成拷貝構(gòu)造函數(shù)代碼,因?yàn)橛脩艚庸芰丝截愓Z(yǔ)義的定義,但是Visual Studio仍然會(huì)生成拷貝構(gòu)造函數(shù)代碼。
-
當(dāng)開(kāi)發(fā)者自己定義了析構(gòu)函數(shù)時(shí)
移動(dòng)構(gòu)造和移動(dòng)賦值都涉及到資源從源對(duì)象移動(dòng)到目標(biāo)對(duì)象,對(duì)于源對(duì)象來(lái)說(shuō)是釋放了對(duì)資源的所有權(quán)。而析構(gòu)函數(shù)是釋放資源,所以既然用戶自己定義了用于釋放資源目的的析構(gòu)函數(shù),那么說(shuō)明移動(dòng)的語(yǔ)義無(wú)法保持默認(rèn)的實(shí)現(xiàn),因此編譯器不再自動(dòng)生成移動(dòng)語(yǔ)義的代碼。
-
當(dāng)開(kāi)發(fā)者自己定義了虛析構(gòu)函數(shù)時(shí)
編譯器不再自動(dòng)生成默認(rèn)析構(gòu)函數(shù)代碼。