通俗易懂解释一下C++的构造函数是怎样的呢?
你買了套房,住進去之前得先裝修。
你買個硬盤,用之前得先分區(qū)。
你買個手機,用之前得先裝上sim卡、下載一些必要軟件、注冊/登錄微信/支付寶賬戶。
創(chuàng)建一個對象也一樣:你得到了一塊內(nèi)存;這塊內(nèi)存可能是“二手房”,前任留下的shit什么的都還留在里面,你得先清理(把內(nèi)容置零)、重新裝修(設置一些基礎信息)之后才能入住。
過去,C時代,這些都得你自己照應。如果你忘了,那么訪問了未初始化存儲區(qū)、讀出亂七八糟的東西,你就自認倒霉吧。
C++時代,人們變聰明了:既然裝修是入住前的必要步驟,我干脆把它固定到你的《購房流程指導書》里算了。你交錢買房后,就會有人領你看房、給你談裝修事宜。
這個固定的、執(zhí)行裝修事宜的步驟就是構造函數(shù)。
用偽碼表示的話,對象創(chuàng)建流程是這樣的:
1、用各種奇怪的方式得到一塊內(nèi)存
2、執(zhí)行構造函數(shù),“裝修”這塊內(nèi)存
3、拎包入住
每個人都有自己獨特的口味,每個用戶自定義對象也有不同的初始化流程。
因此,C++做了一個約定:和類名相同的無返回函數(shù)就是它的初始化函數(shù)(構造函數(shù)),編譯器保證在創(chuàng)建一個對象之后、允許你使用它之前,它必定會在這個對象對應的內(nèi)存上執(zhí)行構造函數(shù),按你的要求把對象裝修好。如果你不寫,那么它默認給你個毛坯房(這就是所謂的“默認構造函數(shù)”)。
舉例來說,你打算寫個網(wǎng)游;其中有一個魔法師角色;那么當new一個新的魔法師對象時,你就要給它弄上一套默認的初始裝備:
現(xiàn)在,你聲明一個法師對象,對應的構造函數(shù)就被調(diào)用了:
//自動執(zhí)行Mage(),為它添加一根白板法杖和一件普通法袍 Mage babyMage(); //自動執(zhí)行Mage(法杖類型 法杖, 法袍類型 法袍),給它一套NB的裝備 Mage superMage(天使之杖, 神圣裹尸布);一般來說,你寫了自己的構造函數(shù),就有必要寫出自己的析構函數(shù)。這樣刪除法師對象時,可以把new給他的裝備一起刪掉,以免造成內(nèi)存泄漏:
class Mage {Mage() {//new一個白板法杖//new一件普通法袍}Mage(法杖類型 法杖, 法袍類型 法袍) {//按傳入的法杖類型new一根法杖//按傳入的法袍類型new一件法袍}~Mage() {//刪除法杖、法袍等對象} }C++保證在你調(diào)用delete時,先自動調(diào)用析構函數(shù)(而我們安排在這個函數(shù)里面刪除它的法杖、法袍等對象),再刪除對象占用的內(nèi)存。
以上,就是所謂的RAII機制(Resource Acquisition Is Initialization)。
C++中的RAII機制
等你有了一定的開發(fā)經(jīng)驗,那么一定經(jīng)常聽到“(資源)誰申請誰釋放”原則。基于這個原則才能清晰、準確的界定資源的生存期、控制權。
而RAII天然保證了這個原則被嚴格執(zhí)行:如果任何類/對象都嚴格的管好自己申請的資源、并在析構時確保這些資源被無遺漏的歸還;那么對一個熟練掌握了RAII的程序員來說,只要一個對象的生存期、所有權、引用關系(計數(shù))在設計之初都理清楚了,資源泄露就是不可能的。
為了清晰表達“所有權轉(zhuǎn)移、復制”等相關語義,C++標準庫才提供了shared_ptr、unique_ptr、weak_ptr等“智能指針”;更有趣的是,這些“智能指針”同樣是借助于有保障的構造/析構函數(shù)的自動調(diào)用機制設計的。你必須先透徹理解構造/析構函數(shù),才有可能明白它們的工作原理、甚至自己實現(xiàn)它們(沒錯,過去那個C++標準化/STL庫總是跟不上趟的年代里,很多程序員在自己的工程里手工編寫過shared_ptr)。
Smart pointers (Modern C++)
因此,當其它語言的程序員覺得離開“垃圾回收”都活不成時,資深C++程序員輕蔑的說“資源可不僅僅是內(nèi)存”——沒有嚴格的RAII機制,沒有構造/析構函數(shù)調(diào)用時機的可靠保證,其它語言在管理內(nèi)存之外的資源時,反而要比C++困難。
總結(jié)
以上是生活随笔為你收集整理的通俗易懂解释一下C++的构造函数是怎样的呢?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c++ 交换变量实践
- 下一篇: C++中的RAII机制