C# 如何在C中就地截断数组#

C# 如何在C中就地截断数组#,c#,c++,.net,arrays,memory-management,C#,C++,.net,Arrays,Memory Management,我是说真的有可能吗?MSDN说数组是固定大小的,调整大小的唯一方法是“复制到新位置”。但是,可能有不安全的/一些神奇的内部CLR结构,它们都是用C++编写的,在这里我们有一个完整的内存控制,可以调用 ReLoC/等等。p> 我没有为这个问题提供代码,因为我甚至不知道它是否存在 我不是说Array.Resize方法等等,因为它们显然没有必要的行为 假设我们有一个带有2GB ram的标准x86进程,我有一个由单个阵列填充的1.9GB。然后我想释放一半。所以我想写一些东西,比如: MagicClas

我是说真的有可能吗?MSDN说数组是固定大小的,调整大小的唯一方法是“复制到新位置”。但是,可能有不安全的/一些神奇的内部CLR结构,它们都是用C++编写的,在这里我们有一个完整的内存控制,可以调用<代码> ReLoC/等等。p> 我没有为这个问题提供代码,因为我甚至不知道它是否存在


我不是说Array.Resize方法等等,因为它们显然没有必要的行为

假设我们有一个带有2GB ram的标准x86进程,我有一个由单个阵列填充的1.9GB。然后我想释放一半。所以我想写一些东西,比如:

MagicClass.ResizeArray(ref arr, n)

并且不要脱离内存异常。Array.Resize将尝试分配另一个GB的RAM,并将失败,内存输出为1.9+1>2GB。

您可以尝试
Array.Resize()


您可以尝试
Array.Resize()

realloc
将尝试执行就地调整大小-但它保留将整个内容复制到其他地方并返回完全不同的指针的权利

NET的
List
类暴露了几乎相同的外部行为-如果您发现自己经常更改数组大小,那么无论如何都应该使用该类。它对您隐藏实际的数组引用,以便将更改传播到同一列表的所有引用中。当您从末尾删除项时,只有列表的长度会更改,而内部数组保持不变,从而避免复制

它不会释放内存(您总是可以使用
Capacity=XXX
显式地释放内存,但这会生成阵列的新副本),但同样,除非您使用大型阵列,否则
realloc
-如果您使用大型阵列,yada,yada-我们已经做到了:)

realloc
在.NET的内存模型中没有任何意义-堆会随着时间的推移不断收集和压缩。因此,如果您试图在修剪阵列时使用它来避免复制,同时保持较低的内存使用率。。。不用麻烦了。在下一次堆压缩时,将移动数组上方的整个内存以填充空格。即使可以执行
realloc
,与简单复制数组相比,您唯一的好处是可以将数组保留在旧的活生生堆中—这并不一定是您想要的。

realloc
将尝试执行就地调整大小—但它保留将整个内容复制到其他位置并返回完全不同的指针的权利

NET的
List
类暴露了几乎相同的外部行为-如果您发现自己经常更改数组大小,那么无论如何都应该使用该类。它对您隐藏实际的数组引用,以便将更改传播到同一列表的所有引用中。当您从末尾删除项时,只有列表的长度会更改,而内部数组保持不变,从而避免复制

它不会释放内存(您总是可以使用
Capacity=XXX
显式地释放内存,但这会生成阵列的新副本),但同样,除非您使用大型阵列,否则
realloc
-如果您使用大型阵列,yada,yada-我们已经做到了:)


realloc
在.NET的内存模型中没有任何意义-堆会随着时间的推移不断收集和压缩。因此,如果您试图在修剪阵列时使用它来避免复制,同时保持较低的内存使用率。。。不用麻烦了。在下一次堆压缩时,将移动数组上方的整个内存以填充空格。即使可以执行
realloc
,与简单地复制数组相比,您唯一的好处是可以将数组保留在旧的生存堆中—这并不一定是您想要的。

BCL中的两种数组类型都不支持您想要的。也就是说,您可以实现自己的类型来支持您需要的内容。它可以由标准数组支持,但将实现自己的长度和索引器属性,这将对您“隐藏”数组的一部分

public class MyTruncatableArray<T>
{
    private T[] _array;
    private int _length;

    public MyTruncatableArray(int size)
    {
        _array = new T[size];
        _length = size;
    }

    public T this[int index]
    {
        get
        {
            CheckIndex(index, _length);
            return _array[index];
        }
        set
        {
            CheckIndex(index, _length);
            _array[index] = value;
        }
    }

    public int Length
    {
        get { return _length; }
        set
        {
            CheckIndex(value);
            _length = value;
        }
    }

    private void CheckIndex(int index)
    {
        this.CheckIndex(index, _array.Length);
    }

    private void CheckIndex(int index, int maxValue)
    {
        if (index < 0 || index > maxValue)
        {
            throw new ArgumentException("New array length must be positive and lower or equal to original size");
        }
    }
}
公共类MyTruncatableArray
{
专用T[]_数组;
私有整数长度;
公共MyTruncableArray(整数大小)
{
_数组=新的T[大小];
_长度=尺寸;
}
公共T此[int索引]
{
得到
{
检查索引(索引,长度);
返回数组[索引];
}
设置
{
检查索引(索引,长度);
_数组[索引]=值;
}
}
公共整数长度
{
获取{return_length;}
设置
{
检查索引(值);
_长度=值;
}
}
私有void检查索引(int索引)
{
this.CheckIndex(index,_array.Length);
}
私有void检查索引(int-index,int-maxValue)
{
如果(索引<0 | |索引>最大值)
{
抛出新ArgumentException(“新数组长度必须为正且小于或等于原始大小”);
}
}
}

这真的取决于你到底需要什么。(例如,您是否需要截断以便于从代码中更轻松地使用它?或者perf/GC/内存消耗是一个问题?如果是后者-您是否执行了任何测量,证明标准数组。调整大小方法不适用于您的情况?

BCL中的数组类型都不支持您想要的。也就是说,您可以实现自己的类型来支持您需要的内容。它可以由标准数组支持,但将实现自己的长度和索引器属性,这将对您“隐藏”数组的一部分

public class MyTruncatableArray<T>
{
    private T[] _array;
    private int _length;

    public MyTruncatableArray(int size)
    {
        _array = new T[size];
        _length = size;
    }

    public T this[int index]
    {
        get
        {
            CheckIndex(index, _length);
            return _array[index];
        }
        set
        {
            CheckIndex(index, _length);
            _array[index] = value;
        }
    }

    public int Length
    {
        get { return _length; }
        set
        {
            CheckIndex(value);
            _length = value;
        }
    }

    private void CheckIndex(int index)
    {
        this.CheckIndex(index, _array.Length);
    }

    private void CheckIndex(int index, int maxValue)
    {
        if (index < 0 || index > maxValue)
        {
            throw new ArgumentException("New array length must be positive and lower or equal to original size");
        }
    }
}
公共类MyTruncatableArray
{
专用T[]_数组;
私有整数长度;
公共MyTruncableArray(在