对象如何存储在堆中?

对象在堆中的存储方式。例如,自行车类可以按如下方式定义:

public class Bicycle {

   public int gear;
   public int speed;

   public Bicycle(int startSpeed, int startGear) {
       gear = startGear;
       speed = startSpeed;
   }

   public void setGear(int newValue) {
       gear = newValue;
   } 

   public void applyBrake(int decrement) {
       speed -= decrement;
   }

   public void speedUp(int increment) {
      speed += increment;
   }   
}

然后我可以创建一个自行车对象:

Bicycle bicycle = new Bicycle(20,10)

然后,此自行车对象应存储在堆中。但我不明白堆如何准确地存储这些实例变量和方法,如速度和齿轮。我知道堆应该作为树来实现。那么对象是如何存储在树中的呢?另外,当您习惯于发现速度的价值时,时间复杂度是多少?bicycle.speed


答案 1

想让别人做你的CS作业吗?;)

根据语言的不同,确切的实现将有所不同(它如何存储在内存中),但一般概念是相同的。

你有你的堆栈内存和堆内存,局部变量和参数进入堆栈,每当你有东西进入堆时。它被称为堆栈,因为当您声明它或调用函数时,值会被推送到它上面,然后弹出并超出范围。new

                    +--------------+
|              |    |              |
|              |    |              |
|              |    |              |
|              |    |              |
|              |    |              |
|              |    |              |
+--------------+    
     Stack                Heap

每个实例变量占用其类型(取决于语言)的内存量,编译器将其全部相加,这就是类型(à la C++)。方法进入代码空间并且不会进入对象(我认为现在你最好在学习记忆是如何组织的时不要考虑这一点,只要把它想象成魔术)。sizeofnew

因此,在您的示例中:

Bicycle bicycle = new Bicycle(20,10)
  • bicycle是对堆内存地址的引用,今天在大多数语言/系统中,它将在堆栈上花费32位和64位。
  • 在堆中分配内存。编译器计算出 Bike 的大小,并创建分配所需内存量的汇编/机器代码。new

这是内存在此行之后的外观:

                    +--------------+
|              |    | Bicycle obj  |
|              |    |--------------|
|              |    |              |
|              |    |              |
|--------------|    |              |
| bicycle ref  |    |              |
+--------------+    
     Stack                Heap

更具体地说,由于 Bike 类有两个实例变量(或在 Java 中调用的字段),并且两者都是 s,而 Java 中的一个是 32 位或 4 个字节,因此 Bike 对象的大小为 4 个字节 * 2 个字段 = 8 个字节。intint

                   +-------------+
|             |   0| gear        | 
|             |   4| speed       |
|             |    |-------------|
|             |   8|             |
|-------------|  12|             |
| bicycle=0x4 |    |             |
+--------------+    
     Stack                Heap

访问存储器的时间复杂度为O(1)。编译器能够找出 的确切内存地址,因为作为对象中的第二个 int 字段,它位于 bicycle+0x4。speed


答案 2
Bicycle bicycle = new Bicycle(20,10)

引用自行车将被存储,而对象和实例变量将被存储,堆的地址在堆栈中分配,因此意味着堆栈将链接到堆。stackheap