回复:lerit的关于对象中字段的初始化问题
???? 謝謝lerit的對于我的博文《內存探尋1之——值類型和引用類型的內存分配機制》中提到的問題。這里先重述問題:
?"你好,你的文章寫得很好,清晰了很多以前比較模糊的概念,我想提個問題,上面你總結了自定義對象的過程,那三條是按照順序的嗎?
另外,下面這個類,是先實例化字段,還是先構造器,我從第三條中看出是“初始化構造器,對對象字段初始化”,可是好像是構造函數后執行了,請指教
public class c
{
public int a = 9;
public c()
{
a = 0;
}
}"
?
其實我對于字段的初始化以前沒有在意,在這里謝謝你的評論,使我關注到了它。我的解釋是:
?
我的分析:
首先:我理解你的問題主要是:類中的字段(ex,上例中的 a)的初始化問題! (呵呵,希望沒有錯~);
其次:我對于對象的內存分配順序是(由博文《內存探尋1之——值類型和引用類型的內存分配機制》):
?
1.構造實例化對象中TypeHandler所指向的對象(可認為是Method Table),包括實現接口、靜態字段、方法等,并提交至Loader Heap上;
2. 初始化實例的2個附加成員(TypeHandler和SyncBlockIndex),并且將TypeHandler指針指向Method Table;
3.初始化構造器,對對象字段初始化;
?
我想用一例子看一下效果:
?1?//Description:?通過建立類TestClass,演示對象的內存分配機制?2?
?3?//CopyRight:?http://www.cnblogs.com/yangmingming
?4?
?5?//Notes:?為簡便,將類的建立,和實例化類放于一起
?6?
?7?namespace?ConsoleApplication1
?8?{
?9????public??class?TestClass
10?????{
11????????public?int?c?;
12?
13????????public?TestClass(int?cc)
14????????{
15????????????c?=?cc;
16????????}
17?????}
18?}
19?
20?class?Program
21?????{
22?????????static?void?Main(string[]?args)
23?????????{
24?????????????TestClass?tc?=?new?TestClass(5);
25?????????????Console.WriteLine(tc.c);
26?????????}
27?????}
28?//輸出為:5?
? 為說明方便,我們在15行設定斷點,經調試,其界面為:
?
可見,如你所言,對象中字段在調用構造函數前,已經有值了!然而在這里我想我們的理解會有誤差,具體分析如下:
一: 我上面所講的"初始化構造器,對對象字段初始化",可以肯定的說,你理解的與我不同(呵呵,必須的~)。我的理解是——調用構造函數,而其主要作用是對其中字段初始化!(你的理解是先后順序執行?!);
二:我認為可以認為類中字段的直接賦值(如你例中:public int a = 9;) 為在內存直接分配完畢后,給字段相應位置賦值,這或許可以被稱為字段初始化(雖然我對這種方式不甚熟悉)。即:對字段的賦值是在我的上述對象內存分配過程3過程之前執行的!
三:從我的上例中看到,當未對字段賦初值時(實質上,系統出于C#的類型安全性要求會對字段類型分別賦初值0或null), 在調用構造函數前字段已經采取了初始賦值:0;
?
附:之所以會對我的說明產生誤解(或者,我的說明不清晰)主要因為
1;在C++中,構造函數的作用即:為字段賦初值;
2:關于初始化,在C++中是不允許直接使用: public int a = 9;的,這樣會報錯。它采用了一種比較特殊的為字段初始化的方式(提供默認值-聲明與定義分離,這里不闡述)。而C#中的字段初始化應在內存分配完成后直接完成的;
3:因為我雖然學習了C#,可能由于還沒有在工作中更多實踐,所以C++思想還很"豐富"的緣故(呵呵,盡快轉變~);
?
最后,還是感謝lerit的問題,讓我有了更多思考,希望以后繼續交流!
?
?
?
??
?
轉載于:https://www.cnblogs.com/yangmingming/archive/2010/02/09/1666859.html
總結
以上是生活随笔為你收集整理的回复:lerit的关于对象中字段的初始化问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用GeocodeService进行地理
- 下一篇: Memcached安装和基本使用