Struct與Class辨析
《2010 .NET面試題整理之基礎篇》文中第十三題為:
==========================================
13、在dotnet中類(class)與結構(struct)的異同?
Class可以被例項化,屬於引用型別,是分配在記憶體的堆上的
Struct屬於值型別,是分配在記憶體的棧上的。
==========================================
什麼時候dotnet中類與結構的異同變成一個是分配在堆上一個分配在棧上了?搜尋引擎一搜,網上全是這種說法,嚇一跳。順藤摸瓜,原來是出自《[你必須知道的.NET] 第四回:後來居上:class和struct》。
我個人不認同這種觀點,我認為它們的本質區別不是分配在棧和堆的問題,甚至跟分配在棧和堆關係不大,而是下面兩點:
· struct的例項 所佔記憶體大小是固定的,class例項 所佔記憶體大小是不固定的(因為可以繼承);當然,從另一個角度解讀就是class是可繼承的,而struct是不可以繼承的;這是一個硬幣的兩面;這是它們在儲存上的區別,你可以把struct當作閹割後的class。
· struct 預設 是傳值,但可以傳引用,class則預設傳引用,無法傳值。這是它們在使用上的區別。
下面展開說幾點:
(1)class也可能分配在棧上(特例)
Int32[] cache = new Int32[100];
cache一個陣列,是class,使用 new 關鍵字,它是分配在堆上的。
Int32* cache = stackalloc Int32[100];
當使用 stackalloc 它就是分配在棧上了。
值型別陣列是特例,但這一特例就夠了,表明class是可以分配在棧上的。一般的class是無法分配在棧上的,編輯器解釋說無法知道size。當然,你也可以認為陣列是一個特殊的型別,這個特例不算。實際上,這裡的陣列已經丟失了class的特徵了,你再也無法用陣列類去引用它了。如果去除這個特例,則class無法在棧上分配。但是,你也可以這樣理解——不是不能,而是不為,微軟目前還不想這樣幹。因為雖然class的size是不確定的,但一個class的例項存在一個最小size,只分配這個最小size的記憶體即可——C++就這樣乾的。微軟不支援,可能他們認為這樣沒必要,不必要搞這麼複雜。一般來說,能夠stackalloc 值型別陣列就足夠了。
(2)struct也可以分配在堆上
這個無須解釋。任何class裡面的struct都是分配在堆上的(通過stackalloc分配的陣列除外)。有沒辦法直接分配呢?我試了幾分鐘,沒發現把struct直接分配在託管堆上的方法,但卻可以通過Marshal.AllocHGlobal方法分配在非託管堆上。因此,有兩種方法可以struct分配在堆上:
(a)設struct是某個class的成員,可將struct分配在託管堆上
(b)使用Marshal或自己寫的記憶體分配器,可將struct分配在非託管堆上
(3)struct也可以傳引用
struct預設是傳值的,在安全環境下,使用ref關鍵字可以傳引用,在非安全環境下,使用指標可以傳引用。
(4)引入struct是為了解決效能問題——小粒度物件的傳值比傳引用效率高。同時,在非安全程式碼中,可以使用struct以及指標和非託管資源互動。
本文轉自xiaotie部落格園部落格,原文連結http://www.cnblogs.com/xiaotie/archive/2010/03/31/1701056.html如需轉載請自行聯絡原作者
xiaotie 集異璧實驗室(GEBLAB)
相關文章
- Swift語言中class、struct、enum的聯絡與區別SwiftStruct
- Swift中Class和Struct異同SwiftStruct
- C++基礎:: struct vs classC++Struct
- typedef and struct inside class definition?StructIDE
- swift中Class和Struct的區別SwiftStruct
- 何時用 struct?何時用 class?Struct
- 深入理解Swift中的Class和StructSwiftStruct
- C++中 struct 和 class 的區別C++Struct
- C++中struct 和 class的區別C++Struct
- C++ class 和 struct 可以相互繼承嗎C++Struct繼承
- C# 中 Struct 和 Class 的區別總結C#Struct
- C++基礎(八)struct和class的區別C++Struct
- 深度辨析 Python 的 eval() 與 exec()Python
- MySQL裡null與空值的辨析MySqlNull
- [Swift]陣列元素是class和struct時的引用測試Swift陣列Struct
- 窺探Swift之別具一格的Struct和ClassSwiftStruct
- B樹與B+樹區別辨析
- 【CSS】nth-child 與 nth-of-type辨析CSS
- this與class(原型)原型
- Type與Class
- 字串的建立辨析字串
- 結構體定義:struct與typedef struct 用法詳解和用法小結結構體Struct
- class與dex檔案
- 過去分詞的辨析分詞
- Vue Class與Style繫結Vue
- vue Class 與 Style 繫結Vue
- vue 的 class 與 style 使用Vue
- Object與Class的關係Object
- class語法與繼承繼承
- 易於混淆的兩個技術:Kerberos與Kubernetes辨析ROS
- 上下文 Context 與結構體 StructContext結構體Struct
- C與C++中struct使用的區別C++Struct
- struct和typedef struct 有什麼不同呢?Struct
- toString && valueOf && Symbol.toPrimitive 辨析SymbolMIT
- 3. Struct 與 物件導向 |《 刻意學習 Golang 》Struct物件Golang
- Ruby Struct EqualStruct
- 結構 STRUCTStruct
- Delphi中布林型別辨析 (轉)型別