代码之家  ›  专栏  ›  技术社区  ›  morowinder

何时在c#中的堆栈上分配数组?

  •  33
  • morowinder  · 技术社区  · 9 年前

    我一直试图弄清楚什么时候在堆栈上分配了东西,但我无法弄清楚如何让数组(或其中的值)在堆栈上进行分配;

    在此示例中:

    public void foo()
    {
        int bar[] = new int [10];
    }
    

    堆上会分配10个int结构,堆栈上只有指向它们的指针,对吗?

    如何将固定大小的数组放到堆栈上?如果我使用的是我定义的灰泥呢?

    如果我希望数组大小作为参数传递给函数怎么办?

    据我所知,若调用函数时大小已知,那个么在调用函数时在堆栈上获取任意大小的数组应该不会有问题。

    我应该为此烦恼吗?据我所知,在堆栈上获得这个固定大小的数组将提高性能,因为不进行堆分配。

    2 回复  |  直到 3 年前
        1
  •  33
  •   Community CDub    7 年前

    堆上会分配10个int结构,堆栈上只有指向它们的指针,对吗?

    是的,正确。

    如何将固定大小的数组放到堆栈上?如果我使用的是我定义的灰泥呢?

    这个 stackalloc keyword 为此目的。然而,这仅在不安全的环境中有效,在大多数情况下,这是一个不必要的限制因素,不值得牺牲性能。

    例子:

    public void unsafe foo()
    {
        int* bar = stackalloc int [10];
    }
    

    你必须使用 pointer arithmetic 以访问阵列的成员。

    如果我希望数组大小作为参数传递给函数怎么办? 据我所知,若调用函数时大小已知,那个么在调用函数时在堆栈上获取任意大小的数组应该不会有问题。

    预期工程:

    public void unsafe foo(int length)
    {
        int* bar = stackalloc int [length];
    }
    

    我应该为此烦恼吗?据我所知,在堆栈上获得这个固定大小的数组将提高性能,因为不进行堆分配。

    不,一般不会。除非您处理一些非常具体的性能关键场景,如繁重的数学计算、加密、压缩等,否则它不会带来真正的好处。

    此外,请参见 this question 用于性能相关的讨论。

        2
  •  3
  •   James Wilkins    2 年前

    评论中提到了这一点,但没有人愿意更新任何答案,所以我发布了一个。C#现在有一种特殊的结构类型,可以很好地用于此目的:

    public void foo()
    {
        Span<int> bar = stackalloc int [10];
    }
    

    摘自文件:

    Span是在堆栈上而不是托管堆上分配的ref结构。引用结构类型有许多限制,以确保它们不能被提升到托管堆,包括它们不能被装箱,它们不能被分配给Object、dynamic或任何接口类型的变量,它们不能是引用类型中的字段,它们不能跨等待和收益边界使用。此外,对两个方法Equals(Object)和GetHashCode的调用引发NotSupportedException。

    Span<T> Struct