此示例是否生成任何垃圾

本文关键字:任何垃 是否 | 更新日期: 2023-09-27 18:20:00

public class Foo
{
    public void Draw() // Called 60 times per second
    {
        spriteBatch.Draw(new Vector2(x, y), null, Color.White);
    }
    private float x, y;
}

特别是,我想知道new Vector2(x, y)调用是否正在生成垃圾。

我的理解是,由于Vector2类型,并且不存储为引用类型的成员,因此将在堆栈上创建。因此,一旦Draw方法返回,它的内存就会自动回收,不会产生垃圾。

这是对的吗?


编辑

如果我可以要求进一步澄清埃里克·利珀特最初的帖子。

问题1(

这取决于调用函数的第一个形式参数是采用引用类型还是值类型。如果它采用值类型,则否,此处没有生成垃圾。如果它采用引用类型,则该值将被装箱。

那么如果签名恰好是这样的:

public void Draw()
{
    Vector2 vector = new Vector2(x, y);
    spriteBatch.Draw(ref vector, null, Color.White);
}

它会从被装箱的矢量中产生垃圾吗?

问题2(

仅仅因为它不在堆上并不意味着它在堆栈上生成。它可能在寄存器中。

但是我认为从垃圾收集器的角度来看,存储在寄存器中的行为就像存储在堆栈中一样。这是对的吗?

此示例是否生成任何垃圾

我想知道new Vector2(x, y)调用是否正在生成垃圾。

这取决于调用函数的第一个形式参数是采用引用类型还是值类型。如果它采用值类型,则否,此处没有生成垃圾。 如果它采用引用类型,则该值将被装箱。

我的理解是,由于 Vector2 是一种值类型,并且不存储为引用类型的成员,因此它将在堆栈上创建

仅仅因为它不在堆上并不意味着它在堆栈上生成。它可能在寄存器中。

如果签名需要"通过引用"传递结构(使用"ref"或"out"修饰符(,是否有任何装箱?

不。你混淆了两种引用。作为变量别名的"引用"不是对象:

void D(int q) {}
void D(ref int q) {}
void D(object q) {}

第一种方法 D 获取整数的副本。第二个 D 为包含未装箱整数的变量创建别名。第三个 D 采用带框的整数。

我假设从垃圾收集器的角度来看,存储在寄存器中的行为就像存储在堆栈中一样。

这不是一个有效的假设。假设已注册或放置在堆栈上的值包含对垃圾回收对象的引用。抖动有权将已注册的引用与堆栈引用区别对待。例如,假设抖动的寄存器分配算法决定在抖动知道引用将不再取消引用后将该寄存器重用于其他用途。抖动完全可以自由地告诉垃圾回收器引用已消失。通过这样做,即使对象的方法正在执行,GC 线程也可能释放"this"。

当然,抖动也可以自由地使用堆栈,但这将是一个更积极的优化。

正确,Vector2将存在于相关的堆栈帧上(Color也是如此( - 但请注意:因为它没有被传递ref所以该值将被复制到Draw堆栈帧中。 Vector2真的很小(64 位/8 字节(,这很可能不是问题 - 但是一旦每个堆栈帧都完成了Vector2,内存就会被回收。

相关文章: