我知道c#,就像Java一样,将源代码转换为字节码并由VM运行,因为C#案例是CIL存储在汇编中并由CLR执行。开发人员几乎不需要关心变量在堆栈上或堆上的位置(由GC处理)作为c ++,对吧?
他们是否有任何快速而直接的方式来证明变量存储在堆栈或堆上?例如,如果我告诉某人,引用类型变量存储在堆上,或者本地值类型变量存储在堆栈上(对吗?)。我怎样才能明确地表明这一点?在C ++中,我可以获取变量的内存地址,并通过VS内存窗口查看存储在堆栈或堆内存中的值。
答案 0 :(得分:23)
开发人员几乎不需要关心变量在堆栈或堆上的位置,对吧?
右。为存储选择的技术是运行时的实现细节。
我注意到您已将省略的寄存器作为存储的可能选择。注册了很多变量,所以它们既不会堆栈也不会堆积。
更好的方法是考虑短期存储和长期存储。
是否有任何快速而直接的方法来证明变量存储在堆栈上或堆上?
尝试计算变量的生命周期。如果您可以轻松地这样做,并且生命周期小于或等于创建它的方法激活的持续时间,那么它很可能在短期池中。如果没有,它可能在长期池中。
在C ++中,我可以获取变量的内存地址,并通过VS内存窗口查看存储在堆栈或堆内存中的值。
使用&
运算符可以更改存储变量的位置!如果您获取变量的地址,那么就无法注册因为寄存器没有地址。改变它试图描述的东西的技术是一种不可靠的技术。
另外,您可能忘记了在C ++中堆栈和堆不是唯一可能的存储位置。
例如,如果我告诉某人引用类型变量存储在堆上,或者本地值类型变量存储在堆栈上(对吗?)。我该如何明确地表明这一点?
由于这些陈述是 false ,因此您无法在所有中显示。简单地说,引用总是在堆上,并且值类型的局部变量在堆栈上。例如:
void M()
{
string s = "";
...
空字符串位于长期存储池中,但空字符串首先不存储在s
中。 对空字符串的引用存储在s
中。该引用可以放在短期池中。
请记住,参考类型的实际参与者不会进入变量 。引用类型的变量包含引用 - 这就是他们称为引用类型的原因。
现在,引用类型的字段是变量,而变量没有已知的生命周期,因此 变量必须放在长期存储池中:
class C { public int x; }
...
C M() { C c = new C(); return c; }
x
是值类型的变量,但由于它是属于引用类型的字段,因此它必须位于长期池中。 c
是引用类型的变量,因此它包含引用;变量c
的生命周期很短,因此c
会出现在短期池中。再次不要将引用与引用的内容混淆。
示例:
Action<int> M()
{
int x = 123;
return y => { x = y; Console.WriteLine(x); };
}
本地变量x
属于值类型,但您无法计算其生命周期,因此它必须位于长期存储池中。
由于你的声明引用类型的变量在堆上,而值类型的局部变量在堆栈上是错误的,所以没有办法证明它的真实性。