将非托管/非托管成员添加到托管类
感谢您的关注。我是一些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)有没有更干净的方法来做到这一点?
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
故障尤其不是你想要隐藏的。
但是你已经完成了工作。
谢谢@ hans-passant!自从我已经是纯粹的C++,但是新到VS2013之后,还有一个跟进。我如何检查课程是否是一次性的?他们在宣言中是否都很明显?我还看到像POD('bool'等),'array ^'和'String ^'之类的东西,例如我无法获得'ref class array'的源码? –
hahaha
当它实现IDisposable接口。对象浏览器可以告诉你,一个。 POD永远不会。 –