仅仅声明一个简单类型的变量会分配内存吗?

use*_*077 4 c# variables declaration

我用 C读过这个问题,我在 C# 中也有同样的问题。

通过代码说是否正确

int a;
Run Code Online (Sandbox Code Playgroud)

a在初始化之前保留四个未分配的字节?或者初始化是第一次分配字节的地方?

Chr*_*ain 5

没有赋值的 int 声明(如注释中所述)将被编译器优化掉——它根本不会出现在程序中。

假设您在一个函数中(而不是类型定义)并分配 int,则该分配将在函数开始时从堆栈空间进行(即,int 是从已经专用于该线程的内存中分配的,并且不会导致操作系统分配)。

另一方面,如果 int 是类型定义的一部分(并被使用),那么它将增加该类型的每个实例的分配空间,无论该类型最终被分配在哪里(类的堆,结构的堆或堆栈)视使用情况而定)。

在任何情况下,它都不会导致 int 本身的指针或引用。

一些进一步的解释:

原始问题通过示例引用了 int 。int 是一个固定长度(4 字节)的数据结构,因此编译器注意到包含相关声明的方法将需要 4 个字节来存储它。编译器将在为当前线程的方法局部变量(调用堆栈)保留的内存区域中保留 4 个字节,而不是在堆上分配这 4 个字节(它放置引用类型的位置)并产生垃圾收集开销。该内存已在线程启动时从操作系统分配,并且仅为该线程保留。如果线程用完该空间,则称为堆栈溢出。

这里值得注意的是,.NET 实际上有 2 个编译器——将 C# 代码转换为 IL 的 C# 编译器,以及在运行时将 IL 转换为机器指令的 JIT 编译器。在我的回答中,当我说“编译器”时,我正在挥手说明我的意思是哪个编译器,但结果是一样的。

根据评论,如果我这样做......

void Foo() {
  {
    int a = 5;
    Console.WriteLine(a);
  }
  {
    int a = 7;
    Console.WriteLine(a);
  }
}
Run Code Online (Sandbox Code Playgroud)

...那么编译器可能会a为第二个变量重用为第一个变量分配的堆栈空间,因为它们在语义上是不同的。但这是一种优化。

还值得注意的是,调用堆栈包括除方法局部变量之外的其他信息——它包括方法的参数、返回值的空间(如果函数返回引用类型,则为指针)以及返回地址。

最后,我要补充一点,在 C# 中,您的方法可能会被 JIT 编译器内联——这意味着被调用方法的代码可能会被批量复制到调用者的主体中,以避免方法调用的开销。在这种情况下,堆栈帧也将包含被调用方法的局部变量的空间。