0

我正在手动将较小的数组复制到较大的数组中:

T is constrained to class, new()

为什么这会触发 GC?对新数组的赋值不是通过引用吗?为什么旧数组的旧元素仍然被垃圾回收?第一个循环中的赋值是否真的复制了它们?

public void Resize()
{
    T newArray = new T[oldArray.Length * 2];

    for (int i = 0; i < oldArray.Length; i++)
    {
        newArray[i] = oldArray[i];
    }

    for (int i = oldArray.Length; i < newArray.Length; i++)
    {
        // Assign new elements to the new array
    }

    oldArray = newArray;
}
4

1 回答 1

3

只要您调用,new您就会创建对堆上新对象的引用。当您分配参考时

oldArray = newArray;

两个引用都指向新对象。如果没有更多对指向的对象的引用oldArray,则它有资格进行垃圾回收。

参考

释放内存。垃圾收集器的优化引擎根据正在进行的分配确定执行收集的最佳时间。当垃圾收集器执行收集时,它会释放应用程序不再使用的对象的内存。它通过检查应用程序的根来确定哪些对象不再被使用。每个应用程序都有一组根。每个根要么引用托管堆上的一个对象,要么设置为空。应用程序的根包括全局和静态对象指针、线程堆栈上的局部变量和引用对象参数,以及 CPU 寄存器。垃圾收集器可以访问即时 (JIT) 编译器和运行时维护的活动根列表。使用此列表,它检查应用程序的根,并在此过程中创建一个图,其中包含从根可到达的所有对象。不在图表中的对象无法从应用程序的根中访问。垃圾收集器将无法访问的对象视为垃圾,并将释放为它们分配的内存。在收集过程中,垃圾收集器检查托管堆,寻找不可访问对象占用的地址空间块。当它发现每个不可达对象时,它使用内存复制功能来压缩内存中的可达对象,释放分配给不可达对象的地址空间块。一旦可访问对象的内存被压缩,垃圾收集器就会进行必要的指针更正,以便应用程序的根指向新位置的对象。它还将托管堆的指针定位在最后一个可访问对象之后。请注意,仅当集合发现大量无法访问的对象时才会压缩内存。如果托管堆中的所有对象都在一个集合中存活,那么就不需要内存压缩。为了提高性能,运行时在单独的堆中为大对象分配内存。垃圾收集器自动释放大对象的内存。但是,为了避免移动内存中的大对象,不会压缩此内存。运行时在单独的堆中为大对象分配内存。垃圾收集器自动释放大对象的内存。但是,为了避免移动内存中的大对象,不会压缩此内存。运行时在单独的堆中为大对象分配内存。垃圾收集器自动释放大对象的内存。但是,为了避免移动内存中的大对象,不会压缩此内存。

于 2013-04-28T17:33:30.893 回答