2017-10-07 163 views
1

感谢您的关注。我是一些VS2013代码的新手,它是C++加上一些微软特定扩展的混合体。该代码有像将非托管/非托管成员添加到托管类

ref class Foo { 
    Bar^ bar_; // somewhere else, bar_ = gcnew Bar... 
}; 

类现在我需要添加一个托管成员,从网上搜索好像我可以做

ref class Foo { 
    Bar^bar_; 
    Unmanaged* ptr_; // somewhere else, ptr = new Unmanaged(); 
    ~Foo() { 
     this->!Foo(); 
    } 
    !Foo() { 
     delete ptr_; 
     // do I need anything to deal with bar_? 
    } 
}; 

的问题是:

1)这是终结者/析构者的路要走吗?

2)我是否需要为bar_写入任何额外的内容,现在我明确写了终结器/析构函数?

3)有没有更干净的方法来做到这一点?

回答

3

1)是这个终结器/析构函数的路要走吗?

是的。

2)我是否需要写什么额外的bar_

没有什么,从片段明显。但是如果Bar类是一次性的,那么你可能应该在析构函数中加上delete bar_;。不是终结者。而且,如果您将引用传递给其他代码,则不能确保该引用是最后一个仍在使用Bar对象的引用。

3)有没有更干净的方法来做到这一点?

不,还有其他办法。例如,你可以考虑不要添加析构函数。有人给出了使用该类的代码调用它的负担。通常这会是C#或VB.NET代码,它将不得不使用using语句或显式调用Dispose()。请记住,他们经常忘记。或者没有一个好的方法来称呼它。

如果这样的代码不会创建大量的Foo实例,并且Unmanaged类仅仅使用了一点内存,那么终结器就足够好了。或者,如果Foo对象预期会在应用程序的整个生命周期中生存下来,这很常见,那么处置就毫无意义。即使它使用了大量的内存,GC :: AddMemoryPressure()也是一个不错的选择。使您的课程更易于使用。

你可以考虑将Unmanaged指针包装在它自己的类中,这样Foo就不再需要终结器了。按照.NET中SafeHandle类的模式,SafeBuffer是最接近的匹配项。然而,在C++/CLI包装中,这往往是矫枉过正的,delete故障尤其不是你想要隐藏的。

但是你已经完成了工作。

+0

谢谢@ hans-passant!自从我已经是纯粹的C++,但是新到VS2013之后,还有一个跟进。我如何检查课程是否是一次性的?他们在宣言中是否都很明显?我还看到像POD('bool'等),'array ^'和'String ^'之类的东西,例如我无法获得'ref class array'的源码? – hahaha

+1

当它实现IDisposable接口。对象浏览器可以告诉你,一个。 POD永远不会。 –