c#结构/类堆栈/堆控制? 在C++中,它非常容易。要在堆上分配任何类/结构,请使用new。如果你想把它放在堆栈上,不要使用新的

c#结构/类堆栈/堆控制? 在C++中,它非常容易。要在堆上分配任何类/结构,请使用new。如果你想把它放在堆栈上,不要使用新的,c#,stack,memory-management,heap,C#,Stack,Memory Management,Heap,在C#中,我们总是使用new关键字,这取决于它是在堆栈还是在堆上分配的结构还是类(结构到堆栈,类到堆)-在某些应用程序中,当更改设计时,只有那些真正属于堆的对象才会进入堆,这可能会造成巨大的性能差异 我想知道的是,有没有一种直接的方法来控制对象的分配位置,而不管它是声明为struct还是class?我知道可以将值类型(结构)装箱到堆中(但是装箱/取消装箱会以性能为代价)。有没有办法在堆栈上分配类 还有,是否有任何机制来分配原始内存,并在C++中使用一些新的放置方式?我知道这打破了被管理的想法,但

在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);
    }
}
struct Foo1
{
公共国际一级;
公共基金;
公共双d;
}
结构Foo2
{
公共食品1[]酒吧;
公共void Init(){
bar=新Foo1[100];
对于(int i=0;i<100;i++)
bar[i]=新Foo1();
}
}
班级计划
{
静态void Main(字符串[]参数)
{
DateTime=DateTime.Now;
Foo2[]arr=新的Foo2[1000000];
对于(int i=0;i<1000000;i++)
{
arr[i]=新的Foo2();
arr[i].Init();
}
WriteLine((DateTime.Now-time.totalmillizes);
}
}
这在我的机器上需要1.8秒才能执行(注意,实际上只有分配在进行-没有参数传递)


如果Foo1从struct更改为class,则执行需要8.9秒!这要慢五倍

您对值类型与引用类型的位置(堆栈与堆)的解释并不完全正确

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

您应该阅读以更好地了解不同类型的实际分配位置

另一方面,在.Net中,您真的不应该关心类型的分配位置—正如Eric Lippert所写的:。您最好理解类型如何传递(通过值、be引用等)的语义

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


这不是最重要的问题。您应该决定类型是否应该具有传递值语义。如果没有,那么它可能应该是引用类型

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

在块中,可以使用在堆栈上分配对象并将其用作指针

引用他们的例子:

// 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]);
   }
}
//cs\u关键字\u stackalloc.cs
//编译时使用:/unsafe
使用制度;
课堂测试
{
公共静态不安全void Main()
{
int*fib=stackalloc int[100];
int*p=fib;
*p++=*p++=1;

对于(int i=2;i<p>),不用担心,你的头仍然在C/C++的世界里,它可以在事情上发生很多事情。在CLR团队中有一群聪明的人整天都在担心让这个神奇的速度。 c#中有一些陷阱,内存使用通常与意外创建大量小对象有关(在循环中执行string=string+其他string是一个经典)

有一个memprofiler,它会告诉你如果你真的认为你有一个由内存管理引起的性能问题,会发生什么


我已经编写了大量高性能代码(图形渲染客户端、网络服务器)在C++中,不必担心这个< /p> 这是错误的查看C结构中的结构和类的方法。在C语言中,结构和类之间的区别不是在它被分配的地方,而是在拷贝语义上。一个结构有值语义,一个类有引用语义。堆栈上的ECT具有值语义,堆上的对象具有引用语义


如何分配内存是运行时的一个实现细节。运行时可以使用堆栈、堆或它喜欢的任何其他混合分配方案。虽然结构通常会在堆栈之类的东西上分配,类会在某种堆上分配,但这不是必需的。例如,在一个未超出函数范围的函数可以很容易地分配到堆栈上。

不要被
new
关键字所愚弄,它对于结构是可选的

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

对于那些确实需要控制的罕见情况,C#with rea中存在不安全(非托管)部分