结构数组和 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
直接存入数组。堆上只有一个分配。访问字段不涉及间接。字段的内存地址可以直接根据数组的内存地址、数组中项的索引和字段在值类型中的位置来计算。
昨天我在阅读 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
直接存入数组。堆上只有一个分配。访问字段不涉及间接。字段的内存地址可以直接根据数组的内存地址、数组中项的索引和字段在值类型中的位置来计算。