菜梗談 C 值型別與引用型別

2021-09-30 06:54:58 字數 1483 閱讀 1313

菜梗談 - c#值型別與引用型別

c#與c/c++的乙個重要區別就是變數的儲存形式。c/c++通過變數的定義方式決定變數的儲存形式,例如:

假如你宣告了乙個class a

可以看出,c/c++因為指標的緣故,資料可以被指標間接地引用,而被間接引用的,可以是棧中的資料,也可以是堆中的資料,甚至,指標可以強制轉換型別,這使得c/c++在擁有強大靈活性的同時,型別安全性變得非常薄弱。而c#,是一門非常強調型別安全的語言,對此,它的做法,就是將所有的型別分成兩種形式:值型別和引用型別。

c#的值型別和引用型別的區別就是它們的儲存形式:值型別儲存在棧空間中,而引用型別儲存在堆空間中。

從淺面上看,c#的值型別包括c/c++中的基本型別,比如int、long、float等,同時還包含struct;c#的引用型別就是class,還有string(string 比較特殊,先不談它)。假定我們已經宣告了乙個struct person,我們可以編寫如下語句:

但如果person定義了乙個預設建構函式,且功能是對person中的字段進行初始化,那麼,下面的做法會更好,而且往往推薦那麼做:

在這裡,即使你使用了new,它還是被分配在棧空間中,new僅僅表示它會呼叫person的建構函式。

但是,我們假定將以上person定義成乙個class,我們編寫類似的語句:

所以在c#中,總是使用下面的寫法例項化乙個物件,而物件,也永遠儲存在堆空間中

所以說,c#是通過型別本身決定儲存形式的。

其實,在c#中,int、long、float等基本型別都是struct,這是它們在c#中的別名,它們對應的全稱是system.int32、system.int64、system.float。所以,c#只有兩種型別struct和class,它們都直接或間接地繼承自system.object。

string也屬於class,也就是說它的資料是分配在堆空間中的,但是它在使用方式上卻更像值型別,如:

由於.net framework的一些底層處理,str1和str2並不同時指向乙個例項,而是分別指向不同的例項,對str2的改寫是不會影響到str1的(其實,當你改寫str2的時候並不是改寫原有的例項,而是分配了乙個新例項,而原來的例項因為不再有引用將會被gc**)。

c#的值型別和引用型別有了非常明確的界限,但是,我們有時卻要將值型別轉換成引用型別或是將引用型別轉換成指型別,這種情況非常之多,例如,你要將int型別變數儲存到集合類中,或是從集合類中取出資料給int變數,這就涉及到boxing(裝箱)和unboxing(拆箱),c#中的裝箱和拆箱,就是為這種目的而設計。它們的工作方式其實很容易理解,所謂裝箱,就是將值型別做乙份拷貝,而這份拷貝,被放入堆空間中,如:

i的資料被拷貝乙份放入了堆空間,並且由j引用,因為值型別也是繼承自object,所以,是完全可行的。這就是裝箱的操作,而拆箱,採用一下方式:

拆箱是裝箱的反操作,它將裝箱到堆中的資料重新放入棧中。

---------

菜梗談 - 甜菜的讀書筆記

---------

sep 15.2010

C 值型別與引用型別

1.主要內容 型別的基本概念 值型別深入 引用型別深入 值型別與引用型別的比較及應用 2.基本概念 c 中,變數是值還是引用僅取決於其資料型別。c 的基本資料型別都以平台無關的方式來定義,c 的預定義型別並沒有內置於語言中,而是內置於.net framework中。net使用通用型別系統 cts 定...

c 引用型別與值型別

c 的值型別包括 結構體 數值型別,bool型,使用者定義的結構體 列舉,可空型別。c 的引用型別包括 陣列,使用者定義的類 介面 委託,object,字串。在c 中函式傳值的特點 1.對於複雜的資料型別,按引用傳遞的效率更高,因為在按值傳遞時,必須複製大量的資料 2.除非特別指定,所有的引用型別都...

C 值型別與引用型別

資料型別分為 值型別 引用型別 值型別 int char double bool 結構 struct 列舉 enum 儲存在堆疊中 引用型別 類 string。陣列 介面 儲存在託管堆中 2.值型別 變數儲存物件的值,賦值會建立值的副本,修改任何乙個副本,不會影響其他的 副本 int x 5 int...