来自Game Development Stack Exchange的

This question was migrated,因为可以在Stack Overflow上进行回答。
                            Migrated 7年前。
                        
                    
                
                            
                    
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方法返回,应自动回收其内存,而不产生垃圾。

那是对的吗?



编辑

如果我可以要求进一步澄清Eric Lippert的初始职位,

问题1)


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


然后,如果签名恰好是这样的:

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


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

问题2)


  仅仅因为它不在堆上并不逻辑上就意味着它是在堆栈上生成的。它可以在寄存器中。


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

最佳答案

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


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


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


仅仅因为它不在堆上并不逻辑上就意味着它是在堆栈上生成的。它可以在寄存器中。


  如果签名需要传递结构“ by ref”(使用“ ref”或“ out”修饰符),会不会有拳击?


不。您正在混淆两种参考。作为变量别名的“引用”不是对象:

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


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


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


这不是一个有效的假设。假设已注册或放置在堆栈上的值包含对垃圾收集对象的引用。抖动具有处理注册参考与堆栈参考不同的权利。例如,假设抖动知道寄存器将不再被取消引用后,抖动的寄存器分配算法决定将该寄存器重新用于其他用途。抖动是完全自由的,然后可以告诉垃圾回收器该引用已消失。这样,即使在执行对象的方法时,GC线程仍可能释放“ this”。

堆栈当然也可以自由地进行抖动处理,但这将是更加积极的优化。

关于xna - 这个样本会产生垃圾吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8793525/

10-13 09:10