去年我正在阅读C#参考资料,在那里我看到了一个声明。请看下面的陈述。
上下文
使用结构而不是类的Point可以使数量有很大差异 在运行时执行的内存分配。下面的程序创建并初始化一个包含100个点的数组。 将Point实现为一个类,实例化了101个独立的对象 - 一个用于数组,另一个用于数组 对于100个元素。
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);
}
}
如果将Point实现为结构,如
struct Point
{
public int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
只实例化一个对象 - 数组的对象。 Point实例在内部分配 阵列。这种优化可能被滥用。使用结构而不是类也可以使应用程序运行得更慢或占用更多内存,因为按值传递结构实例会导致该结构的副本 创建
问题: 这里我的问题是如何在值类型和参考类型的情况下完成内存分配?
混乱: 为什么在参考指南中提到仅初始化1个对象。根据我对Array中每个对象的理解,将分配一个单独的内存。
修改:可能重复 这个问题与jason建议的可能重复的问题略有不同。我关注的是如何仅在值类型和参考类型的情况下分配内存,而该问题只是解释了值类型和参考类型的概述。
答案 0 :(得分:19)
参考类型的数组和值类型的数组之间的差异可能更容易理解为插图:
每个Point
以及数组都在堆上分配,数组存储对每个Point
的引用。总共需要N + 1个分配,其中N是点数。您还需要一个额外的间接访问来访问特定Point
的字段,因为您必须通过引用。
每个Point
都直接存储在数组中。堆上只有一个分配。访问字段不涉及间接。字段的内存地址可以直接从数组的内存地址,数组中项的索引以及值类型中字段的位置计算。
答案 1 :(得分:6)
具有引用类型的数组将包含一组引用。每个引用指向包含实际对象的内存区域:
array[0] == ref0 -> robj0
array[1] == ref1 -> robj1
...
因此,引用数组有一个内存分配(size:arraylength * sizeof(reference)),每个对象有一个单独的内存分配(sizeof(robj))。
具有值类型(如结构)的数组将仅包含对象:
array[0] == vobj0
array[1] == vobj1
...
所以jst一个内存分配大小arraylength * sizeof(vobj)