结构数组和 Class 对象的内存分配

Memory Allocation for an Array of Struct and Class Object

昨天我在阅读 C# 参考资料时看到了一条语句。请看下面的声明。

上下文:

the use of a struct rather than a class for a Point can make a large difference in the number of memory allocations performed at run time. The program below creates and initializes an array of 100 points. With Point implemented as a class, 101 separate objects are instantiated—one for the array and one each for the 100 elements.

class Point
{
    public int x, y;
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
class Test
{
  static void Main() {
          Point[] points = new Point[100];
          for (int i = 0; i < 100; i++)
          points[i] = new Point(i, i*i);
      }
}

If Point is instead implemented as a struct, as in

struct Point
{
     public int x, y;
     public Point(int x, int y) {
         this.x = x;
         this.y = y;
     }
}

only one object is instantiated—the one for the array. The Point instances are allocated in-line within the array. This optimization can be misused. Using structs instead of classes can also make an application run slower or take up more memory, as passing a struct instance by value causes a copy of that struct to be created.

问题: 这里我的问题是在值类型和引用类型的情况下如何完成内存分配?

困惑: 为什么参考指南中提到Only 1 Object will be initialized。根据我对 Array 中每个对象的理解,将分配一个单独的内存。

编辑:可能重复 这个问题与杰森建议的可能重复的问题有点不同。我关心的是在值类型和引用类型的情况下如何分配内存,而这个问题只是解释值类型和引用类型的概述。

具有引用类型的数组将由引用数组组成。每个引用指向包含实际对象的内存区域:

array[0] == ref0 -> robj0
array[1] == ref1 -> robj1
...

所以有一个引用数组的内存分配 (size: arraylength * sizeof(reference)) 和每个对象的单独内存分配 (sizeof(robj))。

具有值类型(如结构)的数组将仅包含对象:

array[0] == vobj0
array[1] == vobj1
...

所以只有一个内存分配,大小为 arraylength * sizeof(vobj)

也许引用类型数组和值类型数组的区别用图解更容易理解:

引用类型数组

每个 Point 以及数组都分配在堆上,数组存储对每个 Point 的引用。您总共需要 N + 1 次分配,其中 N 是点数。您还需要一个额外的间接访问特定 Point 的字段,因为您必须通过引用。

值类型数组

每个Point直接存入数组。堆上只有一个分配。访问字段不涉及间接。字段的内存地址可以直接根据数组的内存地址、数组中项的索引和字段在值类型中的位置来计算。