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

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

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

有人知道吗?

【问题讨论】:

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

标签: c# .net memory-management stack


【解决方案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) 都将具有相同的内存占用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-27
    • 1970-01-01
    • 1970-01-01
    • 2020-01-01
    • 2018-05-03
    • 2018-02-13
    • 1970-01-01
    • 2014-02-02
    相关资源
    最近更新 更多