【问题标题】:Do properties/methods in classes take space in memory?类中的属性/方法是否占用内存空间?
【发布时间】:2013-10-21 17:50:05
【问题描述】:

如果我们有这样的代码:

public class Enemy
{
   public int hp;
}

然后Enemy 对象在 32 位机器中将占用 4 个字节,在 64 位机器中占用 8 个字节(如果我错了,请纠正我)。

如果我们把它改成这样:

public class Enemy
{
   public int hp;
   public void Attack() {}
}

Enemy 对象仍将占用与以前相同的内存量,对吧?

这个也一样:

public class Enemy
{
   private int hp;
   public int Hp { get { return hp; } set { hp = value; } }
}

据我所知,属性是函数,但被视为变量,对吧?

如果我们这样做:

public class Enemy
{
   public int Hp { set; get; }
}

这是否意味着Enemy 对象现在根本不占用内存空间?这没有任何意义。

或者甚至这个,就此而言:

public class Enemy
{
   public void DoSomething() { }
}

谁能解释一下?

【问题讨论】:

  • 至少 - 一个类的每个实例都需要至少一个指向它的指针,否则它将被垃圾回收。还有一些框架开销的附加信息,这些信息会有所不同。每个方法所需的内存量因实现而异。尝试计算此类语言中使用的每个字节可能非常困难,因为您无法直接控制它。为什么你需要知道?还是只是关于自动属性?
  • 我只是想了解这个东西是如何工作的。我最初要求了解有关属性的信息。但既然它们就像函数,我也想了解它们。
  • object would take 4 bytes in 32-bit machines, and 8 bytes in 64-bit (correct me if I'm wrong) 我不确定。无论您运行的是 32 位还是 64 位,int 都将是 4 个字节,这就是它被命名为 Int32 的原因。我认为您将IntPtrint 混淆了。有错请指正

标签: c# function object memory properties


【解决方案1】:

C# 中的int 始终是System.Int32,无论是 32 位还是 64 位应用程序,它都会占用 4 个字节的空间。

但是,对象中有额外的开销。 Jon Skeet 有一篇博文详细介绍了其中的一些内容,Of memory and strings

如您所见,当以 32 位运行时,对象的基本大小为 12 字节,即使您没有字段。

但是,您是对的,具有代码的属性不一定会增加对象的大小。

但是,如果您将其设为自动属性,如下所示:

public int Hp { get; set; }

然后编译器会自动为您创建一个支持字段来保存该属性的值,这将再次占用空间。

【讨论】:

    【解决方案2】:

    public int Hp { set; get; } 表示 - AUTOgenerate 变量,以及它的访问方法,所以这个变量会占用空间,和你手动定义的一样。

    更多细节:

    您的代码被编译为任何类型的二进制代码(纯机器代码或字节代码) - 因此,您的代码在存储在 HD 上或在 RAM 中运行期间总是占用一些内存,而且 - 对于任何类,在运行时为此类的变量分配了额外的内存,因此所有类都占用内存,没有变量的类为每个实例使用几乎 0 额外内存,但每个实例可能有一些“技术”数据,例如 vrtbl,所以通常 - 所有类和所有对象都会占用一些内存

    【讨论】:

    • 感谢您的回答。
    【解决方案3】:

    public int Hp { set; get; }是一个自动实现的属性,编译时会生成一个私有字段。

    喜欢:

    public class Enemy
    {
       public int Hp { set; get; }
    }
    

    将被实现为。

    public class Enemy
    {
       private int _hp;
    
       public int Hp 
       { 
           get { return _hp; }
           set { _hp = value; }
       }
    }
    

    另外添加额外的方法将使用额外的内存,但不是每个实例。 看:Where are methods stored in memory?

    【讨论】:

    • 谢谢。但是我的第二个例子呢,我有一个函数和一个变量,这需要多少内存? (我想这将需要与我的第三个示例相同的数量,对吧?)
    • 哦,是的,我看过你的编辑,是的,我记得读过。所以,就像代码(函数)占据相同的空间,即使我有很多对象。这是有道理的,因为它只是代码,他们都使用它,所以我猜它是在对象之间共享的,对吧?
    • 嗯,从你给我的链接:“类字段存储在堆中”是真的,即使对于微不足道的数据类型,如 int、float 等?我以为那些住在堆栈中。但我想,由于类对象本身存在于堆中,这就是为什么它的所有成员也都在堆中,因为它们在堆中,对吗?
    • 一个类是一个引用类型。 (因为当你新建一个类时,堆上会分配内存)。这就是为什么他们的字段在堆上。(甚至是值类型字段)。只有结构体(包含值类型的文件)在声明为局部变量时才存在于堆栈中。
    • 值类型的值,例如结构和所谓的“普通数据类型”,存储在它们声明的地方,除非经过优化。如果它们被声明为局部变量,它们可能在堆栈或寄存器中,除非它们在闭包、迭代器块或异步方法(它们实际上是类)中声明。如果它们被声明为类中的实例字段,它们将存储在位于其中一个堆上的对象中。另见blogs.msdn.com/b/ericlippert/archive/2009/04/27/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-26
    • 1970-01-01
    • 2014-02-08
    • 1970-01-01
    相关资源
    最近更新 更多