Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 堆栈和堆内存效应?_C#_.net_Memory Management_Stack_Heap - Fatal编程技术网

C# 堆栈和堆内存效应?

C# 堆栈和堆内存效应?,c#,.net,memory-management,stack,heap,C#,.net,Memory Management,Stack,Heap,在以下代码中: MyClass oMyClass1; MyClass oMyClass2 = null; 我的疑问是,上述两行将如何影响内存(堆栈和堆) 是否将在堆栈中创建引用?严格来说,这取决于代码所在的位置 如果代码位于常规函数/方法中,则只会影响堆栈。这对堆没有影响,因为还没有构造MyClass对象 假设MyClass是一个类(即引用类型),则每个声明都会在堆栈上保留足够的空间来保存对MyClass对象的引用 这两个声明稍有不同——第一个声明尚未初始化,因此在将其设置为某个值之前尝试访问

在以下代码中:

MyClass oMyClass1;
MyClass oMyClass2 = null;
我的疑问是,上述两行将如何影响内存(堆栈和堆)


是否将在堆栈中创建引用?

严格来说,这取决于代码所在的位置

如果代码位于常规函数/方法中,则只会影响堆栈。这对堆没有影响,因为还没有构造MyClass对象

假设MyClass是一个类(即引用类型),则每个声明都会在堆栈上保留足够的空间来保存对MyClass对象的引用

这两个声明稍有不同——第一个声明尚未初始化,因此在将其设置为某个值之前尝试访问myclass1将导致编译器错误。第二个是初始化的,因此不会出现编译器错误[尽管如果在将omiclass2的方法或属性设置为引用实际对象之前访问它,会出现运行时错误,例如,使用omiclass2=new MyClass();]

如果代码位于类声明中:

class Fred {
    MyClass oMyClass1;
    MyClass oMyClass2 = null;
}
然后,它将仅在Fred构造函数期间执行。在调用构造函数之前,堆上已经分配了空间(用于Fred对象,包括用于两个MyClass引用的空间)。这两行代码实际上没有任何效果,因为空格已经初始化为null


如果它位于结构声明内部,则效果类似,仅在堆栈(如果结构是本地的)或全局变量内存(如果结构是静态的)上。[虽然,公平地说,我有点不确定在C#中静态是如何分配的-我只是假设它是以与C++类似的方式完成的]

严格地说,这取决于代码的位置

如果代码位于常规函数/方法中,则只会影响堆栈。这对堆没有影响,因为还没有构造MyClass对象

假设MyClass是一个类(即引用类型),则每个声明都会在堆栈上保留足够的空间来保存对MyClass对象的引用

这两个声明稍有不同——第一个声明尚未初始化,因此在将其设置为某个值之前尝试访问myclass1将导致编译器错误。第二个是初始化的,因此不会出现编译器错误[尽管如果在将omiclass2的方法或属性设置为引用实际对象之前访问它,会出现运行时错误,例如,使用omiclass2=new MyClass();]

如果代码位于类声明中:

class Fred {
    MyClass oMyClass1;
    MyClass oMyClass2 = null;
}
然后,它将仅在Fred构造函数期间执行。在调用构造函数之前,堆上已经分配了空间(用于Fred对象,包括用于两个MyClass引用的空间)。这两行代码实际上没有任何效果,因为空格已经初始化为null

如果它位于结构声明内部,则效果类似,仅在堆栈(如果结构是本地的)或全局变量内存(如果结构是静态的)上。[虽然,公平地说,我有点不确定在C#中静态是如何分配的-我只是假设它是以与C++类似的方式完成的]

我的疑问是,上述两行将如何影响内存(堆栈和堆)

信息不足,有两种可能性:

  • 它们是局部变量。在这种情况下,这两行在堆栈上进行了两次相同的分配(引用,始终为32/64位)(方法执行的时间和时间)。堆上没有分配

  • 它们是类或结构中的字段。在这种情况下,这两行分别在创建引用时分配实例中引用的大小。该实例可以在堆栈(当它们是结构成员时)或堆(类成员)上分配

  • 我的疑问是,上述两行将如何影响内存(堆栈和堆)

    信息不足,有两种可能性:

  • 它们是局部变量。在这种情况下,这两行在堆栈上进行了两次相同的分配(引用,始终为32/64位)(方法执行的时间和时间)。堆上没有分配

  • 它们是类或结构中的字段。在这种情况下,这两行分别在创建引用时分配实例中引用的大小。该实例可以在堆栈(当它们是结构成员时)或堆(类成员)上分配


  • 正如我在一个现已删除的答案中所说的,不是类成员的值类型的实例并不总是存储在堆栈上。如果它们被lambda表达式或迭代器块捕获,则它们将存储在堆上。只有当它们是局部变量时,才会在堆栈上分配引用。如果他们是类成员,他们将在堆上。@Frédéric值得详细说明的是,如果他们被lambda捕获,他们将不再是“本地人”。它们将转换为对闭包类(即包装器对象)上属性的引用。闭包就在堆上。@chibacity,没错,“本地人”确实会被“提升”为成员。@chibacity-我想你只是在重复我在答案中写的东西。如果答案确实是错的,如果你能解释一下如何(我可能会学到一些东西!),我将不胜感激。但谢谢你对Frédéric的评论——我也是这么想的——lambda表达式、匿名代理、Linq等只是创建额外类的简写方式,就我而言,正如我在现已删除的答案中所说的,不是类成员的值类型的实例并不总是存储在堆栈上。如果它们被lambda表达式或迭代器块捕获,则它们将存储在堆上。只有当它们是局部变量时,才会在堆栈上分配引用。如果他们是类成员,他们将在堆上。@Frédéric值得详细说明的是,如果他们被lambda捕获,他们将不再是“本地人”。它们将转换为对闭包类(即a)上属性的引用