从 .NET 的 Stack<T> 类中弹出项目会减少内存使用量?

Posted

技术标签:

【中文标题】从 .NET 的 Stack<T> 类中弹出项目会减少内存使用量?【英文标题】:Popping item from .NET's Stack<T> class reduces memory usage? 【发布时间】:2018-03-15 02:21:05 【问题描述】:

从 .NET 的 Stack&lt;T&gt; 弹出项目是否会减少该堆栈的内存使用量?

MSDN 说 Stack&lt;T&gt; 是作为一个数组实现的,所以我猜想通过弹出一个项目,只有顶部元素的指针会移动到前一个元素,保持所有元素不变。

有人知道吗?

【问题讨论】:

每次添加/删除元素时不断调整数组大小会不会很昂贵? 当您在自己的应用程序中实际从堆栈中删除项目时发生了什么?内存使用量下降了吗? 不,只有 TrimExcess() 这样做。它有一个好名字。不要经常使用它,它很贵。 据我所知,它不会缩小到更小的尺寸,它只会将指针向后移动(至少在没有 TrimExcess() 的 List 中会发生这种情况)。不过,我很想听听更多。 【参考方案1】:

看一下源码:https://referencesource.microsoft.com/#System/compmod/system/collections/generic/stack.cs,fd86d7436e55c84b,references

    // Pops an item from the top of the stack.  If the stack is empty, Pop
    // throws an InvalidOperationException.
    /// <include file='doc\Stack.uex' path='docs/doc[@for="Stack.Pop"]/*' />
    public T Pop() 
        if (_size == 0)
            ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EmptyStack);
        _version++;
        T item = _array[--_size];
        _array[_size] = default(T);     // Free memory quicker.
        return item;
    

它不会调整数组的大小,但它会将数组中的位置设置为default,因此,如果它是引用类型,垃圾收集将清理曾经存在的对象,从而释放内存。如果它是一个值类型,它不会有任何区别。

【讨论】:

您在哪里看到数组正在调整大小? 对不起,你是对的,它实际上并没有调整大小。只是 _size 的值发生了变化。 可能更“正确”的说法是先前位于数组最后位置的项目将被收集(最终)。值本身不会设置为 default,而是数组的最后一个(可用)元素。【参考方案2】:

不,堆栈的内存使用将保持不变。但是,如果T 是引用类型并且弹出的元素没有其他实时引用,那么它最终可能会被 GC 收集并且弹出实例的内存将被回收,但这不会以任何方式影响内存使用堆栈本身。

如果T 是一个值类型,那么它根本没有区别,因为任何给定的Tdefault(T) 都将具有相同的内存占用。

【讨论】:

以上是关于从 .NET 的 Stack<T> 类中弹出项目会减少内存使用量?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查 Stack<T> 是不是为空

C#栈的简单介绍

泛型ListHashTable

如果类成员来自另一个类,如何完成构造函数?

模板类和主要

为啥 .NET 中没有 Tree<T> 类?