同时看了好几本书,对变量的内存分配概念总是稀里糊涂的。所以干脆专门写一篇文章来对C#内存分配进行研究和总结。
1、值类型和引用类型
对值类型:
- 值类型实例通常存在线程的堆栈里。即所有值类型的非成员数据都放在线程的堆栈里。
- 如果值类型是类的数据成员,那么值类型实例是存放在托管堆里的。
- 如果值类型装箱转换为引用类型,其类型的数据拷贝到托管堆里的,也就是说,装箱后的值类型是存放在托管堆里。
- 可能还有其他情况,我知识有限,暂时没法知道。
对引用类型:
-
1)引用类型实例为非成员数据时(一般为局部变量),引用是在线程的堆栈上,而引用的所有数据都存在托管堆里。
-
2)引用类型实例为成员数据时,引用和其指向的所有数据都放在托管堆上。
比如 class A 包含 class B;A 实例作为非成员数据,A放在线程的堆栈里,而A里的所有数据
都放在托管堆里。因为 B 被 A 包含,B和B的所有数据都放在托管堆里。(由于目前没有找到满意的答案,书上也没有细说,所以也不太确定B和B的所有数据分配的托管堆是一块邻近的内存地址,还是 B 放在分配给A的托管堆以及B的所有数据放在分配给B的托管堆里)
2、疑惑点
静态和非静态数据分别存放在哪一块内存里呢?
有些书哪怕是经典的书(比如《C# 高级编程》、《C# 图解教程》、《CLR C#》、《Microsoft.NET 框架程序设计》),都没有提到静态以及非静态数据的内存分配。按理说,根据 C/C++ 分配内存的规则,静态数据是存放在静态区的。
可是C# 似乎没有提到“静态区”这一概念。
有些书对引用类型和值类型的一些相关知识点的描述是这样的:
1)
出自:《C# 图解教程》
-4.8.1 存储引用类型对象的成员:
对于引用类型的任何对象,它所有的数据成员都存放在堆里,无论它们是值类型还是引用类型
- 4.8 值类型和引用类型
非成员数据的存储:“对于值类型,数据存放在栈里”
我的理解是:
我的理解:
1、”它所有的数据成员都存放在堆里“
我会默认为,所有数据成员包括了静态和非静态的数据成员。
可是仔细想想,如果静态数据存放在堆里,那么这块数据不可能在程序运行过程中,被释放掉。
不过是由 CLR 来托管堆的,静态数据内存可以被 C