首页新闻招聘找找看知识库

c#值类型和引用类型

0
悬赏园豆:100 [待解决问题]

我们都知道值类型放在栈上,引用类型放在堆上。同时c#是面向对象语言,倡导切皆对象。就算是入口函数Main也是放在类中的,类又是引用类型。那么是否是所有的对象(值类型、引用类型)都是放在堆上的?

内存是一个两个区域(栈、堆)分明

还是说是一个堆中包栈堆的无限循环模式呢?,如果是这种,那么说的装箱问题如何成立呢,因为栈本身就是堆的一部分。

豆子不多,还请各位大神解惑

地对地导弹的主页 地对地导弹 | 初学一级 | 园豆:106
提问于:2017-05-19 17:30
< >
分享
所有回答(8)
0

先弄清楚托管堆和堆栈的区别

~扎克伯格 | 园豆:1656 (小虾三级) | 2017-05-19 17:36
0

简单来说堆只是一块内存.栈是则是代码执行的空间.栈空间是在编译时就已经决定有多大的.堆空间是在运行时动态变化的.
也就是说你在代码里int a=1;

编译器知道代码执行到这里的时候会需要一个int变量的空间.所以在程序初始化.代码还没执行时.就已经分出了一块空间给他.

吴瑞祥 | 园豆:24235 (高人七级) | 2017-05-19 17:37

 我不明白的是 入口函数在类中,类属于引用类型那么必然再堆上了,那么就算是main函数的类(Program)中定义的字段int a=1也在堆上了,还是说编译的时候会把所有的类都整理一遍,把所有的类中的值类型都放到堆上去,这样说不通把,因为要动态创建类型,编译时候、甚至运行的时候都不知道下一步会有多少个值类型变量产生

支持(0) 反对(0) 地对地导弹 | 园豆:106 (初学一级) | 2017-05-19 17:43

 你的误区在于不理解代码执行的位置.

代码不是在对象里执行的.代码是有一个单独的区域.在你看来是  object.方法() 这样调用代码.

但实际上是 方法(object) 这样的.你可以理解成所有代码都是静态的.

然后:是先有的栈.系统再在栈上分配空间.并运行代码.分配的栈空间是用来给代码用的.

支持(0) 反对(0) 吴瑞祥 | 园豆:24235 (高人七级) | 2017-05-19 17:50

 哈哈哈哈.你的名字是敏感词不让发.@dudu

支持(0) 反对(0) 吴瑞祥 | 园豆:24235 (高人七级) | 2017-05-19 17:50

@吴瑞祥: 我有点明白你的意思了,是不是这样呢:class person{int a},内存中并不是像我们写的代码一样在嵌套执行,而是有另一种机制解析。是不是需要看编译原理才能全部搞清楚?

支持(0) 反对(0) 地对地导弹 | 园豆:106 (初学一级) | 2017-05-19 17:53

@吴瑞祥: 哪来的敏感词。。。

支持(0) 反对(0) 地对地导弹 | 园豆:106 (初学一级) | 2017-05-19 17:54

 是的.你需要学编译原理.我是和我邻居家的孩子聊天的时候他告诉我的.

函数的调用和返回是一个压栈.弹栈的操作.这些只要有个基本概念就行.不需要深究.

如果你想对内存管理有深入了解.就把C程序设计重新认真看一遍.

带你名字的时候就会.

添加失败
添加失败:评论中有不合适的内容,不允许发布
支持(0) 反对(0) 吴瑞祥 | 园豆:24235 (高人七级) | 2017-05-19 17:56
0

堆、栈是两块区域。

1.类的成员 字段(静态 、实例)、方法(静态、实例)都分配在堆上。

2.类方法中的局部变量,值类型在栈上,引用类型 同上第1点

Qlin | 园豆:2378 (老鸟四级) | 2017-05-20 09:32

字段是值类型呢?也在堆上?

支持(0) 反对(0) 地对地导弹 | 园豆:106 (初学一级) | 2017-05-20 09:48

字段是值类型在堆上,字段是引用类型 参考 1、2点。

支持(0) 反对(0) Qlin | 园豆:2378 (老鸟四级) | 2017-05-20 09:54
0

不多说内存管理了,可能过长。

说说低级语言动态内存分配(反之静态,这种不怎么提),查找栈上的变量自不必说当前上下文是直接可预测的(因为这本身就是次序的),但堆上的我们得到的是什么——指针(或者引用),它不是次序的,是散列随机性的。

如果按照堆为根(后面的说法) ——那么肯定就没有内存泄漏一说了。高级语言(虚拟机类)没有内存泄漏并不是因为堆得的作用域,而还是根据栈的作用域,只是为每个引用做了引用计数,比如变量a=new Form,static b = a;技术为2,假设a作用域过了 Form仍然在堆上,它很明显没有受到a作用域影响,直到b作用域过了计数被置为0了,才发生内存释放(虚拟机当然释放还有代的过程)。

其实是堆为根还是栈为根,你看函数就清楚了(一进去就是main嘛)。 

这种问题也不必过于纠结 —— 因为内存管理的设计不是恒定的,上面的举例也只是win的写照,比如没有操作系统的时候,没有内存管理的时候,那就是根据自己的需求快速定制的结构。

但凡靠谱的程序有个通行的做法——往往对象数量>1,就需要进行管理(如内存、窗口、设备...),你根据适当的场景(参数、要解决的问题,比如Android的窗口和WinForm窗口要解决的问题区别比较大)分析思考,然后缩小范围定位之即可测试得到答案。

花飘水流兮 | 园豆:2658 (老鸟四级) | 2017-05-20 22:52
0

值类型可以存储在堆和栈上,它是局部变量时存储在栈上,如果值类型是作为类的一个属性,那么就会存储在堆上;

引用类型有两块内存,一块存储引用地址(栈上),一块存储实际的对象(堆上)。

骨灰仔(原名反骨仔) | 园豆:360 (菜鸟二级) | 2017-05-21 15:30
0

参考:http://www.cnblogs.com/anding/p/5229756.html

/*梦里花落知多少*/ | 园豆:161 (初学一级) | 2017-05-21 19:14
0

1、内存不仅仅只有堆区和栈区
2、堆和栈是程序运行时申请分配的内存空间
3、推荐你去看CLR via C# 里面有一节好像就提到了这个问题

老乌尼 | 园豆:198 (初学一级) | 2017-05-24 22:47
0

堆和栈的区别,你可以这样理解,堆和栈都是内存上的空间,栈是有编译器进行分配,堆是有开发人员编写的程序分配,堆上存储的是实际值,但是堆上实际值的引用地址是存在栈上记录的,查找堆上的值是先通过栈上引用的内存地址来进行实际的值使用,这也就是引用类型,而栈上的值是没有地址引用,是直接储存的实际的值,这也就是值类型的存储,这是堆栈在存储上的区别,它们代表的是不同的数据结构,你所谓的拆箱装箱,通过上面不同的存储地方,应该能明白,把堆栈上的数据进行相应的转换的时候是有相应的开销的,因为它们的存储地址发生了改变。纯手打,望采纳!

流年莫逝 | 园豆:242 (菜鸟二级) | 2017-05-27 14:15
   您需要登录以后才能回答,未注册用户请先注册