【问题标题】:Does declaring a variable already occupy memory声明变量是否已经占用内存
【发布时间】:2013-08-09 05:38:58
【问题描述】:

您好,我一直在寻找这个问题的答案。 我想知道我的代码何时会占用内存。

例如。 int myVar;

  1. 此代码是否已占用内存?内存是指堆栈吗? 最初在 .NET 中,我注意到这条线的默认值为零(0)。
  2. 但变量真正存储的是什么?值 ZERO 还是存储值 ZERO(0) 的地址?

另外,我对引用类型的理解是,当我编写这行代码时

MyClass 我的对象; // 只声明

myObj = new MyClass() //创建实例

我想知道幕后发生了什么。我的假设正确吗? myObj 将驻留在堆栈中,并且 myObj 能够存储地址。在我创建一个实例时 该对象是在堆上创建的,并且该对象的地址被传递给 myObj 变量。

问题是,我想知道以下两者之间是否更有效(内存方面和性能方面)。

代码 1: int myVar; myVar = FunctionThatReturnsAnInteger(); Console.WriteLine(myVar);

代码

Console.WriteLine(FunctionThatReturnsAnInteger());

我想要一个很好的解释,类比很方便。

提前致谢。 :)

【问题讨论】:

  • 我尝试创建一个指针,2 个不同的未初始化整数变量。一次分配两个整数的地址并分别打印它们。他们显示了两个不同的地址。我推断在声明时它们已经占用了内存?
  • 有关更多信息,您应该查看以下链接:msdn 特别是 从 ValueType 派生的类型在 CLR 中具有特殊行为。值类型变量直接包含它们的值,这意味着内存是在声明变量的任何上下文中内联分配的,对于引用值创建对象时,内存分配在托管堆上,并且该变量仅包含对对象位置的引用
  • @Marco 感谢您的回答和良好的链接。你能回答我最后一个问题,哪个占用更多内存。声明一个变量并捕获函数调用的返回值并显示它或直接调用函数并将返回值用作 Console.WriteLine() 的参数
  • 我已阅读 Jon Skeet 的 article,它清楚地回答了我的问题。他真的是这里最好的人之一。
  • @KiXOrtillan:在 Jon Skeet 的文章中补充一点:任何被快速赋值、使用过一次并被遗忘的变量几乎肯定只会在 JITTING 之后驻留在寄存器中。

标签: c# .net performance memory-management


【解决方案1】:

性能效率 - 更高效,但仅通过几条指令,从执行堆栈存储和加载变量。请记住,抖动可能会在运行时优化您的代码,从而删除任何不必要的指令。

内存效率 - 效率更高,因为执行堆栈上没有定义本地变量。

代码清晰 - 变量的定义更接近它的使用位置,使代码更可用。在我看来,将一种方法返回到另一种方法会更干净,但也有缺点,即更难检查返回的值(但在 VS 2013 中这是可能的)。

带有临时变量的IL:

  // Code size       13 (0xd)
  .maxstack  1
  .locals init ([0] int32 myVar)
  IL_0000:  call       int32 StackOverflowScratchPad.Program::FunctionThatReturnsAnInteger()
  IL_0005:  stloc.0
  IL_0006:  ldloc.0
  IL_0007:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_000c:  ret

和没有:

  // Code size       11 (0xb)
  .maxstack  8
  IL_0000:  call       int32 StackOverflowScratchPad.Program::FunctionThatReturnsAnInteger()
  IL_0005:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_000a:  ret

奖励 - 在声明中为 temp var 赋值时的 IL:

  // Code size       15 (0xf)
  .maxstack  1
  .locals init ([0] int32 myVar)
  IL_0000:  ldc.i4.5
  IL_0001:  stloc.0
  IL_0002:  call       int32 StackOverflowScratchPad.Program::FunctionThatReturnsAnInteger()
  IL_0007:  stloc.0
  IL_0008:  ldloc.0
  IL_0009:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_000e:  ret

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-29
    • 1970-01-01
    • 1970-01-01
    • 2011-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-04
    相关资源
    最近更新 更多