c++創建對象過程詳解


創建對象的過程

1.分配內存空間

2.初始化成員變量

3.調用構造方法

 

1. 分配內存空間(A a 和 new A的不同)

對於全局對象靜態對象以及分配在棧區域內的對象,對它們的內存分配是在編譯階段就完成了,

而對於分配在堆區域內的對象,它們的分配是在程序運行階段完成的

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

內存空間的分配過程中需要確定分配空間的大小,即類對象的大小,這個問題是編譯器根據類數據成員來進行分配。

是否有足夠的內存空間來滿足分配,對於不同的情況我們需要具體問題具體分析:全局對象和靜態對象。編譯器會為他們划分一個獨立的段(全局段)為他們分配足夠的空間,一般不會涉及到內存空間不夠的問題。分配在棧區域的對象。棧區域的大小由編譯器的設置決定,不管具體的設置怎樣,總歸它是有一個具體的值,所以棧空間是有限的,在棧區域內同時分配超過空間大小的對象會導致棧區域溢出,由於棧區域的分配是在編譯階段完成的,所以在棧區域溢出的時候會拋出編譯階段的異常。分配在堆區域的對象。堆內存空間的分配是在運行是進行的,由於堆空間也是有限的,在棧區域內試圖同時分配大量的對象會導致分配失敗,通常情況會拋出運行時異常或者返回一個沒有意義的值(通常是0)。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

2.初始化成員變量(初始化 和 賦值)

初始化(Initialization)---------初始化列表實現

這一階段是對象創建過程中最神秘的一個階段,也是最容易被忽視的一個階段。要想知道這一階段具體完成那些任務,關鍵是要區分兩個容易混淆的概念:初始化 (Initialization)和賦值(Assignment)初始化早於賦值,它是隨着對象的誕生一起進行的。而賦值是在對象誕生以后又給予它一個新的值。這里我想到了一個很好的例子:任何一個在醫院誕生的嬰兒,在它誕生的同時醫院會給它一個標識,以防止和其他的嬰兒混淆,這個標識通常是嬰兒母親所在床鋪的編號,醫院給嬰兒一個標識的過程可以看作是初始化。當然當嬰兒的父母拿到他們會為他們起個名字,起名字的過程就可以看作是賦值。經過初始化和賦值后,其他人就可以通過名字來標識他們的身份了。區分了這兩個概念后,我們再轉到對對象初始化的分析上。對類對象的初始化,實際上是對類對象內的所有數據成員進行初始化。C++已經為我們提供了對類對象進行初始化的能力,我們可以通過實現構造函數的初始化列表(memberinitialization list)來實現。

初始化列表先於構造函數體內的代碼執行;

賦值(Assignment)--------------構造函數函數體內賦值實現

對象經過初始化以后,我們仍然可以對其進行賦值。我們可以通過構造函數的實現體(即構造函數中由"{}"包裹的部分)來實現。

由以上的分析可以看出,構造函數實現了對象的初始化和賦值兩個過程:對象的初始化是通過初始化列表來完成,而對象的賦值則才是通過構造函數,或者更准確的說應該是構造函數的實現體。

 

3.調用構造函數

構造函數的使用

•構造函數重載
     –構造函數也是函數,擁有重載的特征
     –重載的構造函數在構造對象時根據參數自動選擇

•構造函數可以使用默認參數
     –構造函數也擁有函數參數默認值的特性
     –使用默認值可以減少構造函數的個數

•構造函數的初始化列表
     –初始化列表可以讓構造函數在被調用之前進行初始化工作
     –如果類的成員變量是const或引用類型,必須使用初始化列表初始化

注意:在什么情況下必須使用初始化列表來初始化成員變量而不能使用構造函數賦值來實現?

當類的成員變量是const 或者 引用類型時,必須使用初始化列表進行初始化,原因是:

1. const數據成員只在某個對象生存期內是常量,而對於整個類而言卻是可變的。因為類可以創建多個對象,不同的對象其const數據成員的值可以不同。所以不能在類的聲明中初始化const數據成員,因為類的對象沒被創建時,編譯器不知道const數據成員的值是什么。

2. const數據成員的初始化只能在類的構造函數的初始化列表中進行。要想建立在整個類中都恆定的常量,應該用類中的枚舉常量來實現,或者static cosnt

3. 引用的指向只能初始化,不能修改其指向,賦值過程是在修改其指向,其實這就是賦值和初始化的本質區別

總結: 1 . 對象的創建時先分配對象的存儲,然后調用構造函數(調用代碼段的構造函數並傳遞剛才開辟的內存空間this指針給該函數),有初始化列表的先初始化列表然后再執行構造函數中的函數體復制操作

         2.  成員變量里面有引用類型的變量 或者 是const常量類型的變量  那就必須要使用初始化列表來初始化成員變量。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM