创建值类型时会发生什么?

时间:2010-03-15 18:21:20

标签: c#

我正在开发一个使用XNA和C#的游戏,并试图避免每帧都调用new struct()类型代码,因为我认为它会让GC崩溃。 “但是等等,”我对自己说,“结构是一种价值类型。那时GC不应该被调用,对吧?”嗯,这就是我在这里问的原因。

我对价值类型的变化只有一个非常模糊的概念。如果我在函数调用中创建一个新结构,是否在堆栈上创建了结构?它是否会被推动和弹出,性能不受打击?此外,如果我需要在一次调用中创建多个实例,是否会有一些内存限制或性能影响?

以此代码为例:

spriteBatch.Draw(tex, new Rectangle(x, y, width, height), Color.White);

在这种情况下,Rectangle是一个结构。创建新Rectangle时会发生什么?多次重复该行(比如几千次)会有什么影响?是否创建了这个Rectangle,将一个副本发送到Draw方法,然后丢弃(意味着没有内存被吃掉,在同一个函数中以这种方式调用Draw)?

P.S。我知道这可能是预成熟的优化,但我很好奇,希望能够更好地了解正在发生的事情。

4 个答案:

答案 0 :(得分:4)

当创建一个新的结构时,它的内容被直接放到你指定的位置 - 如果它是一个方法变量,它会进入堆栈;如果它被分配给一个类变量,它会进入被指向的类实例(在堆上)。

当复制一个struct变量时(或者,在你的情况下,传递给一个函数),构成struct的字节都被复制到堆栈上或类内的正确位置(如果你设置了一个字段)或引用类型实例上的属性。)

即使可能存在字节复制,JIT编译器也可能会优化所有不需要的副本,以便尽可能快地执行。一般来说,这不是你需要担心的事情 - 这是一个非常微观的优化:)

这会回答你的问题吗?

答案 1 :(得分:1)

当值类型进入堆栈时,每帧仍然分配和释放所有内存仍然会影响性能 - 特别是在Xbox 360上。在PC上你可能不会注意到差异,但在360上你可能将

答案 2 :(得分:1)

如果在本地声明,则在堆栈上创建值类型,如果是对象实例的一部分(作为对象实例的一部分),则在堆上创建值类型。在任何情况下,GC都不会收集结构实例,当它们的容器超出范围时会被销毁。

MSDN struct (C#)文章提供了更多相关信息。

答案 3 :(得分:1)

这只是为了添加到thecoops答案。对于引用类型,new运算符在堆上分配类型的新实例并调用指定的构造函数。

对于结构体,new运算符根据指定的构造函数初始化字段。但是,可以在不使用new的情况下实例化结构。在这种情况下,结构中的所有字段都是未初始化的,并且在显式初始化之前无法使用。

有关详细信息,请参阅the description on MSDN