C#中普通类、静态类、静态方法、实例方法和数据成员在堆栈上的内存分配?

6
大多数书籍很少讨论程序如何执行以及内存如何在堆栈和堆上分配。数据存储在堆栈上还是堆上需要注意。
假设我有一个普通的类,像这样:
public class MyClass
{
    int Age=0;
    string strName="None"
    Double Salary=0;

    public void Data1()
    {
        Age=30;
        strName="Robin";
        Salary=3500;
    }
}

问题

1)对于上面的类,内存将如何分配。在程序运行时内存将被分配还是在我们创建实例时内存将被分配。当我们通过实例调用Data1()时会发生什么,内存将为函数调用还是数据成员初始化而分配? 告诉我agenamesalary 将分配多少内存。内存将在栈上还是堆上分配。

public class MyClass
{
    static int y=0; 
    static string strComp="None"
    int Age=0;
    string strName="None"
    Double Salary=0;

    public void Data1()
    {
        Age=30;
        strName="Robin";
        Salary=3500;
    }

    public static void Data3()
    {
         y=50;
         strComp="Hello";
    }
}

2) 静态数据成员和函数的内存是如何分配的?当我们调用MyClass.Data3()时,内存是在运行应用程序时分配还是在堆栈上分配?

答:静态数据成员和函数的内存分配发生在程序编译时。它们被分配在全局数据区域,这个区域位于程序的静态存储区中。因此,内存不会在堆或栈上分配。

3) 静态类的内存是如何分配的?静态类存储在堆栈上还是堆上...如果是堆栈,为什么?

答:静态类的实例在堆或栈上分配取决于它是如何声明的。如果静态类是作为局部变量声明的,则它将在堆栈上分配。否则,它将在堆上分配。静态类在堆栈上分配的原因是因为它们的生命周期与其所在的方法相同。当方法完成时,静态类也将被销毁。因此,在堆栈上分配它们可以更有效地管理它们的生命周期。

以上是您提出的几个问题,请详细解释。谢谢。

2个回答

7

1.) 当您创建一个类的实例时,将分配内存。当调用 Data1() 时,不需要额外的内存,因为您只引用了类实例的字段(没有其他局部变量)。由于 MyClass 是引用类型,内存将在托管堆上分配。

2.) 静态方法不消耗任何内存。静态字段在访问任何静态字段或创建包含它们的类型的实例之前进行初始化(在本例中为 MyClass)。

3.) 无法创建静态类的实例,因此不会动态分配内存,仅在创建类型本身时分配内存。静态类保证在程序首次引用该类之前加载并初始化其字段和静态构造函数。一旦创建了静态类,它就会一直驻留在内存中,直到应用程序域关闭。


从你的解释中有几件事情不太清楚。1)当调用instacename.funcname()时,函数和数据成员是否分别分配内存?2)当我们第一次创建类的实例时,静态函数的内存是在什么时候分配的?3)当我们第一次引用类时,如mystaticclass.staticfunction(),静态类的内存是如何分配的?如果我理解不正确,请再讨论一下。 - Mou
1
@user:方法/函数不消耗任何内存,只有“数据”会消耗内存。 - BrokenGlass

2

首先,只有在使用new()指令实际创建一个类实例时才会创建该实例。

MyClass a = new MyClass();

只有当创建新实例时,才会分配内存,包括所有对象的字段。
静态成员不属于类的对象实例。你可以这样想:类本身有一个表示实际类类型的对象,所有静态成员和方法都属于该对象。(实际上并非如此,但用这种方式更容易理解静态概念)。静态类成员在程序开始时创建(或者dll首次加载时)。
当使用new()创建新对象时,它将在堆中创建(连同所有成员)。
在堆栈中创建的变量属于运行时环境中的方法,并且只有在访问声明它们的块之后才能访问。

内存是为函数还是数据成员分配的?当我们创建实例时,如果类有5个函数,则会为所有函数分配内存,或者只在调用函数时按需分配。 - Mou
当您创建一个类的新实例时,将为该实例及其所有成员(如类中定义的)分配内存。方法(函数)局部变量仅在调用该方法时分配。 - Yochai Timmer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接