C#结构体/类堆栈/堆控制?

所以在c ++中很容易。 你想要在堆上分配任何类/结构,使用new。 如果你想在堆栈上,不要使用新的。

在C#中,我们总是使用new关键字,并根据它是一个结构体还是一个类,将它分配到堆栈中或堆上(结构体到堆栈,堆到堆中) - 在某些应用程序中,可以有一个在改变设计时,性能差异巨大,只有那些对象进入真正属于那里的堆。

我想知道的是 - 是否有一种直接的方法来控制对象的分配,而不管它是否声明为struct或class? 我知道价值类型(结构)可以装箱到堆中(但是装箱/拆箱会带来性能成本)。 有没有办法在堆栈上分配类?

另外,是否有任何机制来分配原始内存并使用类似于C ++中的放置新内容? 我知道这是与被管理的想法相违背的 - 但如果你可以使用自定义的内存管理,它会产生巨大的性能差异。

我喜欢C#,因为它很方便,因为它是垃圾回收器和其他东西 - 但有时候,在处理应用程序瓶颈时,希望能够更好地控制实际发生的事情。

任何提示/提示欢迎:)

编辑:性能示例:

struct Foo1
{
    public int i;
    public float f;
    public double d;
}

struct Foo2
{
   public Foo1[] bar;

   public void Init(){
        bar = new Foo1[100];
        for (int i = 0; i < 100; i++)
            bar[i] = new Foo1();
    }
}

class Program
{
    static void Main(string[] args)
    {
        DateTime time = DateTime.Now;
        Foo2[] arr = new Foo2[1000000];
        for (int i = 0; i < 1000000; i++)
        {
            arr[i] = new Foo2();
            arr[i].Init();
        }

        Console.WriteLine((DateTime.Now - time).TotalMilliseconds);
    }
}

这需要1.8秒钟在我的机器上执行(请注意,实际上只有分配正在进行 - 没有参数传递)

如果Foo1从结构变为类,执行需要8.9秒! 这是慢五倍


虽然在一般情况下,对象总是分配在堆上,但C#确实可以让您下降到指针级别以实现繁重的互操作性或非常高性能的关键代码。

在不安全的块中,可以使用stackalloc在堆栈上分配对象并将它们用作指针。

引用他们的例子:

// cs_keyword_stackalloc.cs
// compile with: /unsafe
using System; 

class Test
{
   public static unsafe void Main() 
   {
      int* fib = stackalloc int[100];
      int* p = fib;
      *p++ = *p++ = 1;
      for (int i=2; i<100; ++i, ++p)
         *p = p[-1] + p[-2];
      for (int i=0; i<10; ++i)
         Console.WriteLine (fib[i]);
   }
}

但是请注意,您不需要声明整个方法不安全,您可以对其使用unsafe {...}块。


您对值类型与参考类型的位置(堆栈与堆)的解释不完全正确。

例如,如果结构体是引用类型的成员,它也可以在堆上分配。 或者,如果您在通过对象引用传递它们时装箱了它们。

您应该阅读http://www.yoda.arachsys.com/csharp/memory.html以更好地了解实际分配的不同类型。

在另一个说明中,在.Net中,你真的不应该关心类型的分配位置 - 正如Eric Lippert所写的:堆栈是一个实现细节。 你最好理解类型传递的语义(通过值,引用等)。

此外,您似乎暗示在堆上分配对象比在堆上分配更昂贵。 实际上,我认为复制值类型的性能成本超过了在堆栈上稍微快速分配的任何节省的好处。 堆栈和堆之间最大的区别在于,在大多数CPU架构中堆栈更有可能保留在CPU高速缓存中 - 从而避免高速缓存未命中。

这不是最重要的问题。 您应该确定该类型是否应该具有按值传递语义。 如果它不 - 那么也许它应该是一个参考类型。


不要被new关键字所迷惑,它对于结构体是可选的。

在C#中有一个托管的世界,您可以享受垃圾收集器和类型安全,并且不必担心很多内存细节。 堆栈/堆的差别是无关紧要的,它是关于复制语义的。

对于那些你确实需要控制的罕见情况,C#的不安全(非托管)部分包含实际指针和所有内容。

但是C#中事物的成本与C ++不同,所以不要捕捉鬼魂,非托管的,短暂的对象非常便宜。 编译器可以在堆栈上分配小数组作为优化,您将无法辨别,也不应该关心。

链接地址: http://www.djcxy.com/p/79943.html

上一篇: c# structs/classes stack/heap control?

下一篇: Advantage and disadvantage of using void pointer in C++ pimpl