随笔 - 23, 文章 - 22, 评论 - 144, 阅读 - 25880
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

Struct 和Class 总结

Posted on   雷雷  阅读(277)  评论(0编辑  收藏  举报

面试时经常会被问到这两者的区别,答案似乎是:Class可以被实例化,属于引用类型,是分配在内存的堆上的 ,Struct属于值类型,是分配在内存的栈上的。

看了一老兄的文章,觉得所言有理,下面总结如下:

1. stuct的实例,所占内存大小是固定的;class的实例,所占内存大小是不固定的(因为可以继承),这是他们在存储上的区别。

2.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以及指针和非托管资源交互。

编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示