繁体   English   中英

MichaelJordan在.NET堆栈中创建了几个ValueType实例?

[英]How many ValueType instances does MichaelJordan create on the stack in .NET?

我对如何在.NET中以内存方式管理ValueType对象感到有些困惑。 我知道每个实例/声明的值类型都放在堆栈中。 我不确定什么构成新实例/声明。 我认为我的主要问题是:

如果我将ValueType参数传递给方法,但未为其分配值,那么是否在堆栈上创建了新实例?

我不确定自己的措词是否正确,因此我编写了一个简单的示例程序,以使其更容易理解我的困惑。

void Main()
{
    //-------------------------|  Line 1:
    int MichaelJordan = 23;      
    //-------------------------|  Line 2:   
    int HoursInADay = 24;           
    //-------------------------|  Line 3:
    Console.WriteLine("Michael Jordan is "+(NumberHelper.Is23(MichaelJordan) ? string.Empty : "not ")+"23");
    //-------------------------|  Line 4:
    Console.WriteLine("The last number that wasn't 23 was "+NumberHelper.LastNumberThatWasnt23);
    //-------------------------|  Line 5:
    Console.WriteLine("Hours in a Day is "+(NumberHelper.Is23(HoursInADay) ? string.Empty : "not ")+"23");
    //-------------------------|  Line 6:  
    Console.WriteLine("The last number that wasn't 23 was "+NumberHelper.LastNumberThatWasnt23);
}

public static class NumberHelper {  
    public static int LastNumberThatWasnt23;
    public static bool Is23(int candidate){
        if(candidate != 23){
            LastNumberThatWasnt23 = candidate;
            return false;
        }
        return true;
    }
}

所以,这是我对程序的疑问。

  1. 在此程序中的堆栈上创建了多少个整数实例?

  2. 确切地说,每个值类型实例在代码中的哪个位置创建在堆栈上?

尽管我很可能错了,但这是我认为发生的事情,也是我不确定的事情。

  • 第1行:我知道在堆栈上为变量MichaelJordan创建了一个新实例

  • 第2行:我知道在堆栈上为变量HoursInADay创建了一个新实例

  • 第3行:是否创建了变量MichaelJordan的值实例的副本,以便用作方法参数? 是否创建一个值23的实例用于比较?

  • 第4行: LastNumberThatWasnt23字段的值未初始化,因此它返回默认值。 是否为此字段创建了具有默认值的新实例?

  • 第5行:与第3 相同的问题,但是,我知道在堆栈上为字段LastNumberThatWasnt23创建了一个新实例,因为我正在对其进行设置。

  • 第6行:现在,该字段具有一个值。 但是,在引用该值并将其传递到Console.WriteLine方法时,是否要在堆栈上创建一个新的值实例?

对于这个问题,我还有另外一部分,那就是我如何找出类似的东西? 我可以通过编程方式进行吗? 是否可以使用任何工具来揭示此类信息?

我知道这是一个很长的问题,所以我感谢您抽出宝贵的时间阅读它。

这取决于您的计算机运行该程序所使用的抖动。 但是,由于仅使用两个局部变量,因此正确答案很可能为零。 jit优化器将变量值存储在CPU寄存器中。 这是标准的优化之一。

您将在此答案中找到有关抖动执行的优化的更多信息。

情况很复杂。 抖动几乎可以自由支配。 它可以将局部变量放入寄存器中,或放在堆栈中,或放在两者中,或放在一个寄存器中。 局部变量和堆栈分配之间没有简单的对应关系。

您可以通过反汇编asm代码(而不是IL)找到这些东西。 即使如此,它仍然取决于编译器标志,调试器的存在,方法的确切内容,.net版本,...

但是,为什么这很重要呢? 除非您进行非常深入的递归,否则局部变量消耗的堆栈内存可以忽略不计。

.net框架中的值类型和引用类型的内存分配应该回答大多数(如果不是全部)问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM