2014-10-30 119 views
0

通常,在C++的指针,如果一个人创建一个动态对象传递到函数作为参数,将它做类似垃圾收集器,用于托管C++

Object *myObj = new Object; 
someFunction(myObj); 
delete myObj; 
myObj = nullptr; 

而非

someFunction(new Object); 

为了不泄漏内存。现在假设我正在创建一个垃圾收集对象;这个规则是否仍然适用,或者垃圾回收器是否真的能够从函数调用中创建的内存中删除一个动态创建的对象,如下所示?

someFunction(gcnew Object); 
+0

不应该分配是否在()之间。 – deviantfan 2014-10-30 18:59:47

+0

您不再需要跟踪您使用托管C++创建的对象。即使您在()中创建了对象,您的C++/CLI对象也会按垃圾收集器的预期收集和销毁。 – ArthurCPPCLI 2014-10-31 08:18:39

回答

3
someFunction(gcnew Object); 

好的,没关系。该对象将无法存活很长时间,如果某些功能没有以其他方式存储该引用,则下一代#0集合可能会将其摧毁。您可以声明一个变量,但这没有意义,它将在运行时由抖动优化器删除,并且最终会得到完全相同的代码。


要记住这一点很重要,但是delete运算符仍然存在于C++/CLI中。但是,完全是与它在本地C++中的不同。它调用一个类的IDisposable :: Dispose()实现方法。这提供了“确定性破坏”,就像在C++中一样。不是很合适的话,它确实是确定性清理。该接口由任何托管类实现,该托管类存储“昂贵”的操作系统资源,这种类型在垃圾收集器清理之前不想挂起。

Boilerplate示例是System :: Drawing :: Bitmap类。一个非常小的类,它是大块地址空间和(可能)被锁定的文件的包装。你想确保在你不再需要它时处理它。你可以写这样的代码是这样的:

void dosomething() { 
    Bitmap^ bmp = gcnew Bitmap("foo.png"); 
    drawBitmap(bmp); 
    delete bmp; 
} 

但是,这是不正确的代码,它不是异常安全的。 删除drawBitmap引发异常时,运营商呼叫将被绕过。不是世界末日btw,这实际上并没有造成泄漏,因为GC最终会将清理干净。然而,不愉快的,所以C++/CLI设计师与本地C++ RAII模式的仿真,叫想出了“堆栈语义”,在C++/CLI:

void dosomething() { 
    Bitmap bmp("foo.png"); // NOTE: no^hat 
    drawBitmap(bmp); 
} // <=== bmp is disposed here 

这应该熟悉任何C++程序员:)

0

当您的应用程序中没有更多的引用时,被管对象全部被垃圾收集器销毁。

在你的情况下,如果你的函数没有在其他地方分配你的对象,它将被缓冲,一旦函数返回就被垃圾收集。

0

是的,因为正常运行的垃圾回收器会在分配给该内存的变量超出范围时删除动态分配的内存。例如,在Java中,可以这样说:

button.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent e) 
    { 
     // do something. 
    } 
}); 

并且“ActionListener()”在超出作用域时被删除。我只提到Java,因为它的垃圾收集属性,并意识到这是一个C++问题。我只是用它来解释一个概念。