比如已经存在一个窗体 form2
现在new一个f
Form f=new form2();
请问 此时服务器是不是仅为f分配了一个内存空间 而并未使f指向form2这个窗体?
并且为f分配的内存空间里存放了什么? 是form2的属性和方法吗?
没有吧,你只是声明了
f变量分配在堆栈上,4bt,是一个引用指针,指向form2对象内存;
form2分配在托管堆上,存放它的所用成员。
或许我应该这样问 在一个button的点击事件里有如下代码
{
Form f=new Form2();
f.show();
}
我第一次点击的时候显示了这个页面, 那么这个f是在什么时候释放内存的?
如果是在关闭这个页面的时候关闭,那么 我不关闭的情况下 再次点击按钮 又会 Form f=new Form2()
那么内存中岂不是存在两个f的变量? 这应该不允许啊 不可能存在两个同名的变量啊 求解释清楚啊
@狼之崛起: 用new实例化一个对象后,这个对象是在堆中分配的内存,即一个新的Form2对象,而这个f是在栈中的一个引用变量,指向堆内存中的首地址。
button的点击事件是产生了一个局部变量,你会为for循环内部的一个“string a='0';”担心命名重复的问题吗.
可以简单的理解为f这个引用变量的作用域是在两个‘{}’之间,点击一次按钮后,打开一个新窗口,f就被释放了,但是它指向的堆中的Form2对象还在。
@狼之崛起: 你的理解有错误,new是在内存中开辟一块新的内存空间的意思,当前的窗体为form2,当你点击button时,接着就执行Form f=new Form2();这时就重新开辟内存空间,意味着什么,意味着创建了一个form2的对象,接着执行f.show();这时会弹出一个窗体,这个窗体跟form2一模一样,因为它是form2的对象,它继承了form2的所有属性和方法,f这个对象将在f这个窗体关闭后被销毁,如果不关闭窗体不停地点击button将开辟很多个内存空间(就是创建很多个对象),它们之间都是独立存在的,并不是上面所说的指针引用问题,因为它们都在独立的内存区域,并不是共享一个内存区域。。。。我是这么认为的。
已经存在了,你又new了一个,当然是两个了,窗体和普通的类在这一点上没有任何区别。
这个form2其实是一个class 只是实例化了一个form2类型的窗体而已
我第一次点击的时候显示了这个页面, 那么这个f是在什么时候释放内存的?
如果是在关闭这个页面的时候关闭,那么 我不关闭的情况下 再次点击按钮 又会 Form f=new Form2()
那么内存中岂不是存在两个f的变量? 这应该不允许啊 不可能存在两个同名的变量啊 求解释清楚啊
===============================
解释如下:
1、.net freamwork不需要手工垃圾回收,也不需要c++那样的栈上的垃圾回收。freamwork在判断没有引用之后,在适当的时候——比如内存用尽,比如你现在很闲,会自动垃圾回收。
2、new的时候,在“托管堆”上分配了内存,而栈上只不过是一个句柄,相当于指针,指向目标。在你show的时候就是用的这个句柄调用的。而方法调用结束后,f所在的内存空间被回收——注意这里是句柄/指针本身被回收了,托管堆上的内存,也就是那个窗体没有被回收。
3、你再次单击的时候,重复了上面的操作。所以不存在你说的“内存中岂不是存在两个f的变量”的问题——同时你这样的描述也是不正确的,语言规范规定一个范围内不允许存在两个相同名字的变量,而内存中没有这个限定。同时,在编译后的IL文件中,由于f并非类型,也非函数签名,因此根本不存在所谓的“两个f”。
4、当你关闭窗体时,最后一个引用消失,那个窗体就可以被用于垃圾回收了,在某个适当的,而且没有保证的时候,那个窗体所在的托管堆内存会被垃圾回收。