【发布时间】:2013-06-24 13:51:59
【问题描述】:
背景
我知道编译器会“省略为字段生成 int foo = 0; 之类的代码,因为内存分配器会将字段初始化为默认值。” Reference
class Foo
{
public int a = 1;
public int b = 0;
}
Foo..ctor:
IL_0000: ldarg.0
IL_0001: ldc.i4.1
IL_0002: stfld UserQuery+Foo.a // There is no b.
IL_0007: ldarg.0
IL_0008: call System.Object..ctor
IL_000D: ret
我还知道“编译器会在每个使用局部变量的方法上自动添加.locals init,这表明 JIT 必须在开始执行方法之前注入初始化所有局部变量的代码。” Reference
问题
为什么编译器不为 int foo = 0; 之类的局部变量生成 IL,因为 .locals init 已经涵盖了这一点? (为了与字段保持一致?)
(我知道 C# 规范要求明确分配局部变量,我同意。)
(我引用的链接说明了为什么需要.locals init,以及为什么C#规范需要初始化locals。但没有说明为什么必须存在额外的IL指令来初始化默认值。作为验证过程已被.locals init 保证)
void Main()
{
int a = 0;
int b = 1;
int c = 0;
int d = a + b + c;
d++;
}
.maxstack 2
.locals init (int a, int b, int c, int d)
IL_0000: ldc.i4.0
IL_0001: stloc.0 // a (Can be optimized away)
IL_0002: ldc.i4.1
IL_0003: stloc.1 // b
IL_0004: ldc.i4.0
IL_0005: stloc.2 // c (Can be optimized away)
IL_0006: ldloc.0 // a
IL_0007: ldloc.1 // b
IL_0008: add
IL_0009: ldloc.2 // c
IL_000A: add
IL_000B: stloc.3 // d
IL_000C: ldloc.3 // d
IL_000D: ldc.i4.1
IL_000E: add
IL_000F: stloc.3 // d
【问题讨论】:
-
.locals init是否涵盖此案例?这些是成员变量而不是局部变量,因此处理方式不同? -
好的,既然你已经阐明了这个例子,我明白你的意思了。
-
好像stackoverflow.com/a/3383168/56778 回答了这个问题。
-
如果我猜我会说它与变量的碳足迹有关,那么当方法完成执行时它无论如何都会被 gc'd,该类必须使用 idisposable跨度>
-
@JimMischel 我不认为stackoverflow.com/questions/753438/… 会回答。它说明了
.locals init必不可少的原因,以及 C# 规范要求初始化本地变量的原因。但它没有说明为什么必须存在额外的 IL 指令。 (因为验证过程由.locals init保证)