C++構造函數(shù)深度學習
本文針對C++構造函數(shù)進行深度探究,供大家參考,具體內(nèi)容如下
1、引子:
以下代碼中的輸出語句輸出0嗎,為什么?
struct Test { int _a; Test(int a) : _a(a) {} Test() { Test(0); } }; Test obj; cout << obj._a << endl;
輸出為:-858993460
2、剖析
上面代碼的輸出為一個垃圾值,也就是說obj調(diào)用構造函數(shù)并沒有對成員進行初始化工作,雖然默認無參構造Test()內(nèi)部調(diào)用了Test(int a),但從結果看,初始化工作并不成功。這是為什么呢?
在執(zhí)行構造函數(shù)時,Test()并不會調(diào)用"this"對象(即obj對象)的Test::Test(int a),而是會用Test::Test(int a)來創(chuàng)建一個新的臨時實例對象,然后當這條語句執(zhí)行完后,這個新的臨時對象馬上就會被銷毀。這樣一來,"this"對象就沒有被初始化,成員_a就是垃圾值,以后使用"this"對象就有可能產(chǎn)生一些問題。
3.重點:構造函數(shù)互相調(diào)用
分析完這個題目之后,我們會想到另一個問題。也是我們今天重點關注的問題:
class Test { int _a; int _b; int _c; public: Test(int a, int b) : _a(a), _b(b),_c(0) {} Test(int a, int b, int c); };
如果我們C++類中有兩個構造函數(shù),分別為Test(int a, int b)和Test(int a, int b, int c)。如果我們的構造函數(shù)Test(int a, int b, int c)要完成所有成員(a,b,c)的賦值初始化工作,可以這樣寫:
Test::Test(int a, int b, int c) : _a(a) , _b(b) , _c(c) { }
但是,這樣寫又重復了構造函數(shù)Test(int a, int b)的工作,類成員少的情況下還好,如果成員非常多,重復寫的話代碼量過大,而且代碼可讀性降低了。然而我們可以看到構造函數(shù)Test(int a, int b)已經(jīng)完成了成員a和成員b的賦值初始化工作,為了減少代碼量,就想著讓3個參數(shù)的構造函數(shù)調(diào)用2個參數(shù)的構造函數(shù),然后在執(zhí)行一些自己的代碼,這就如同派生類先調(diào)用基類的同名函數(shù),再執(zhí)行自己特有的代碼。但是這種機制如何實現(xiàn)呢?
之前我們得出過結論:構造函數(shù)調(diào)用另一個構造函數(shù)并不能完成當前對象的初始化工作,只是初始化了臨時對象。下面我們就進入本文的核心問題:如何在構造函數(shù)中調(diào)用本類的另一個構造函數(shù)來初始化當前對象?
方法一:使用placement new技術,在3個參數(shù)中顯式調(diào)用2個參數(shù)的構造函數(shù)。
3參數(shù)構造函數(shù)可以這樣實現(xiàn):
Test::Test(int a, int b, int c) { new (this) Test(a, b); ... }
構造函數(shù)分為2個執(zhí)行階段:一是在初始化列表的初始化階段,二是在構造函數(shù)體內(nèi)的賦值階段。上述方法是在第二個階段調(diào)用2個參數(shù)的構造函數(shù)。
placement new是operator new的一個重載版本,只是我們很少用到它。如果你想在已經(jīng)分配的內(nèi)存中創(chuàng)建一個對象,使用new是不行的。也就是說placement new允許你在一個已經(jīng)分配好的內(nèi)存中(?;蚨阎校嬙煲粋€新的對象。原型中void*p實際上就是指向一個已經(jīng)分配好的內(nèi)存緩沖區(qū)的的首地址。placement new技術的形式是 new(void *p) Type(...),表示在p所指的內(nèi)存區(qū)域調(diào)用Type構造函數(shù),該過程沒有內(nèi)存請求。
這個方法本質就是在對象地址處,調(diào)用2個參數(shù)的構造函數(shù)重新生成一個新的對象然后覆蓋該對象。這個實現(xiàn)方法有投機取巧的嫌疑。
方法二:使用C++11新特性——委托構造函數(shù)(Delegating constructors)??梢栽跇嬙旌瘮?shù)初始化列表直接調(diào)用,類似于調(diào)用基類構造函數(shù)。
Test::Test(int a, int b, int c) : Test(a, b) { ... }
上述說了構造函數(shù)有2個執(zhí)行階段,該方法是在第一個階段進行的,更加方便。但是注意不能在Test(a, b)后面在接_c(c)了,因為調(diào)用2個參數(shù)的構造函數(shù)之后,就相當于該對象已經(jīng)初始化完成了,不能在初始化列表放入其他成員的初始化形式。只能放在構造函數(shù)體中的賦值階段。該方法目前只能用在VS2013中。
這個方法利用了C++11標準中的新特性——委托構造函數(shù)(Delegating constructors)。目前只能再VS2013及以上的版本使用,這個方法局限性很大,不過確實很方便。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
C++實現(xiàn)Matlab的zp2tf函數(shù)的示例代碼
matlab?的?zp2tf?函數(shù)的作用是將極點形式的?H(s)?函數(shù)的分母展開,本文主要為大家介紹了C++實現(xiàn)Matlab的zp2tf函數(shù)示例代碼,需要的可以參考一下2023-04-04C語言中操作sqlserver數(shù)據(jù)庫案例教程
這篇文章主要介紹了C語言中操作sqlserver數(shù)據(jù)庫案例教程,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-07-07