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

我想用C在堆栈上分配一个对象#

  •  2
  • Poni  · 技术社区  · 14 年前

    假设我有这个C级:

    public class HttpContextEx
    {
        public HttpContext context = null;
        public HttpRequest req = null;
        public HttpResponse res = null;
    }
    

    如何在函数内部声明将在堆栈上而不是在堆上分配的对象?
    换言之,我希望避免使用“new”关键字。这个代码是 坏的 :

    HttpContextEx ctx = new HttpContextEx(); // << allocates on the heap!
    

    我知道什么堆栈/堆是完美的,我听说过奇妙的C GC,但是我坚持要在堆栈上分配这个小对象,这只是为了方便起见。

    这种态度来自C++(我的主要工具),所以我不能忽视这一点,我的意思是它真的破坏了我在这里的乐趣。

    4 回复  |  直到 8 年前
        1
  •  9
  •   Destructor    8 年前

    如果将其更改为值类型,请使用 struct 并在方法体中创建一个新实例,它将在堆栈中创建该实例。但是,成员(因为它们是引用类型)仍将在堆中。语言(无论是值类型还是引用类型)仍需要新的运算符,但您可以使用 var 避免重复使用类型名

    var ctx = new HttpContextEx(); 
    

    否则,以C为例,因为GC做得很好。

        2
  •  11
  •   Femaref    14 年前

    你不能(也不应该)那样做。即使你会用 struct (将放在堆栈上),您必须使用 new 包含类的运算符。严肃地说,如果你换一种语言,也要换一种态度。

        3
  •  3
  •   codekaizen    14 年前

    你必须来自C++。在.NET中,情况并非如此。

    所有引用类型都分配在托管堆上,GC在那里跟踪它们。对于由快速退出的函数作用域的对象引用,分配的对象很可能只保留在托管堆的第0代中,这将导致非常高效的内存集合。托管堆被调到处理这样的短期对象。它甚至没有与您可以使用的C++堆相同的分配策略。

    这就是clr的工作原理。如果您想以另一种方式工作,请尝试使用非托管运行时。

        4
  •  1
  •   Guffa    14 年前

    在.NET中,类是引用类型,结构是值类型。

    如果您真的想要在堆栈上分配类型,您可以创建一个结构。但是,有几个理由不:

    • 结构的正确实现更为复杂。在有充分的理由创建结构之前,您应该坚持使用类。
    • 结构用于表示单个单元的类型,而您的类型只是三个独立单元的容器。
    • 结构不应大于16个字节才能有效工作。在32位系统中,您会低于该限制,但在64位系统中,结构要大于该限制。
    • 一个结构应该是不可变的,可以作为一个值类型工作,而您的类型不是。

    最后,在堆上分配小对象本身没有什么不好的地方。内存管理器实际上是专门设计的,可以有效地处理小的短期对象。

    下面是一个代码示例,如果它是一个结构,则不起作用,但是如果它是一个类,则可以正常工作:

    public void SetContext(HttpContextEx ex) {
      ex.context = HttpContext.Current;
      ex.req = ex.context.Request;
      ex.res = es.context.Response;
    }
    
    HttpContextEx ctx = new HttpCoontextEx();
    SetContext(ctx);