public static void Main()
{
Test t1 = new Test();
}
何时t1(引用变量)将在编译时或运行时获得内存 我认为应该是运行时间。但是当我在Main方法中设置断点并监视t1时,它为空。所以这意味着t1在记忆中。
如果我错了,请纠正我。
编辑:我听说静态成员变量是在编译时分配的。
答案 0 :(得分:5)
内存仅在运行时分配(在编译时您的应用程序未运行)。
在运行时,您的t1
变量在赋值发生后只会有一个值(即不是null
),因此它取决于您放置断点的位置。如果你将断点放在Main
方法的右大括号上,并在看到它时检查观察窗口,你会看到我的意思。
即。如果将断点放在赋值行Test1 t1 = new Test1();
上,那么该行尚未执行,因此未进行赋值。
答案 1 :(得分:3)
引用t1在Main方法的堆栈帧上分配 - 您分配给它的值(即'new Test()'部分)在运行时分配在堆上 - 这就是t1变量之前存在的原因该行已执行且为空。
答案 2 :(得分:2)
Test t1;
这部分只为引用分配了足够的空间(在很多情况下可能只有4个字节,但我认为它实际上取决于.NET框架实现),并且在编译时确定并且在调用Main时分配(我认为)
t1 = new Test();
该行在运行时将分配足够的空间来存储Test对象的数据,然后分配现有的引用变量t1以引用新分配的内存。所以现在你有了t1的空间加上新的Test()的空间都被分配了。
编辑:要响应您的编辑,静态成员变量是不同的,并且您的本地变量的行为与它们不同。但是,我不相信在编译时分配静态成员变量。我认为在加载包含它们的类型时会分配它们(这似乎是在调用任何引用该类型的函数时)。
class Test2
{
public static Test f1 = new Test();
}
只要调用包含对Test2类型的任何引用的函数,此代码就会创建一个新的Test实例。
答案 3 :(得分:2)
在'Main'的开头,尚未分配实例的堆内存(并且直到new Test()
才会分配)。它将保持分配,直到它被垃圾收集。
将引用堆内存的局部变量Test t1
(基于堆栈)确实存在(并且在'Main'正在执行的整个时间内存在)。
这两个都是运行时分配,但在内存所在位置和持续时间方面有所不同。
静态字段在类型加载时分配(并在当时和类型首次使用之间的某个时间初始化)。
通过'compile-time',我不确定你是否指的是JIT编译 - 但无论哪种方式,内存都是与编译分开分配的。
答案 4 :(得分:1)
不,这意味着尚未分配t1。一旦你调用new Test()
t1,将分配内存来存储Test
对象的大小,并为其分配一个内存地址。
是内存仅在运行时分配。
答案 5 :(得分:1)
你应该能够自己解决这个问题。试想一下:
分配内存编译时间,没有任何意义......
答案 6 :(得分:1)
在阅读了上述答案之后,让我试着用更好的方式来表达答案。
让我们以这种方式放置代码:
Main()
{
Test t1;
t1 = new Test();
}
现在,让我们开始吧:
让声明{执行 - 没有任何名称为t1 - 为什么??
编程正在运行。 汇编很久以前就完成了。 仍然 - t1永远不会分配内存。为什么呢?
转到下一个调试点,让Test t1
语句执行。
现在检查 - 您会发现本地变量/内存列表中存在t1。
为什么呢?该声明已处理完毕,并且是RUN / RAN / Executed。所以,它被分配了内存。
现在 - 分配了什么内存?它只是 Reference / Pointer / Object所需的内存。 它显然应该具有null值。那么 - 你认为需要多少记忆?
现在让下一个语句执行。
这一次,null的值被其他东西取代 - 这确实占用了可变的内存量,具体取决于它的作用。
处理下一个陈述:
现在发生的事情是您的对象不再存在/或不再被引用。
是否仍然为仍然存在的对象/分配的内存分配了内存
new Test()
为测试t1分配的内存? - 是的!
此内存仍然存在,但幸运的是 - 垃圾收集器存在并清除垃圾。
从效率的角度来看,最好设置Test t1=null
,以便在主函数有很多其他语句可以使用的情况下,它可以解除分配为新测试分配的内存()通过信号通知垃圾收集器不再需要这块数据。
在Main
(或变量的范围)结束时,垃圾收集器检查指针以引用某个值 - 如果它没有(因为它为null),它就会继续也取消分配引用/对象内存。
@Static东西:我试图自己找出静态类/变量和方法。
@people: 如果我在某个地方错了,请纠正我。
答案 7 :(得分:0)
在调试模式下运行应用程序,F5主要是visual studio中的键盘快捷键。在这个声明中加上一个断点。使用F10进入下一个语句。当调试器步骤下一个语句时,您将看到正在创建的对象。