2011-06-10 104 views
2

在几乎完全使用非托管C++之后,第一次编写managed-C++时需要注意哪些最常见的问题?Common managed C++ gotchas

+0

人们仍然使用Managed C++?我认为大多数项目已经转换到C++/CLI。 :-O – 2011-06-10 16:28:07

+1

一个问题就是将它称为托管C++(小写m),因为它是托管代码,不知道在C++/CLI之前有托管C++(其中我们大部分都不会说。) – 2011-06-11 16:48:14

+1

最大的错误是假设它是类似于C++。先写一些C#代码来感受一下托管环境。 – 2011-06-11 18:50:36

回答

2

当您使用内置的IJW(It Just Works)技术将托管代理转换为指向函数的指针时,函数指针不包含对委托来自的对象的引用。如果您不想安排参考,则可以收集管理对象,然后在调用该函数时,您将得到一个NullReferenceException。

如果您正在制作一个采用回调的C库,并且您想将其包装到托管类中,您会遇到很多问题。托管类的客户端将提供一个委托,您将其转换为回调。您还必须保留对委托或目标对象的引用。

这在托管C++和C++/CLI中是正确的。

+0

不是C++ - 特定的,这会影响所有.NET语言。请参阅['Marshal.GetFunctionPointerForDelegate'](http://msdn.microsoft.com/zh-cn/library/system.runtime.interopservices.marshal.getfunctionpointerfordelegate.aspx)。“代理被转换为一个函数指针,可以使用__stdcall调用约定传递给非托管代码。 您必须手动让代理不被垃圾收集器从托管代码收集。垃圾收集器不会跟踪引用非托管代码“。 – 2011-06-11 17:42:03

1

如果你的意思是C++/CLI ...

  • 忘记通过引用传递参数时使用pin_ptr。与此相关,了解跟踪句柄和指针之间的区别至关重要。请参阅Expert C++/CLI的第一章。
  • C++/CLI没有C#的yield构造,在使用TestCaseSource属性编写单元测试和Nunit来生成测试用例数据时,我们使用它很多。这与下一个有关。
  • 实施系统:: IEnumerable是非常麻烦的。但一旦你做了一次,你有一个参考,所以它没有那么糟糕。
  • 理解析构函数和终结器之间的区别非常重要。对于这个讨论,再次看到Expert C++/CLI
1

第4章下面是另一个疑难杂症:在对象上执行的方法不构成对对象的引用。这意味着在对象的成员方法执行期间,但在最后一次引用this之后,可能会在方法仍在执行且终结器可能触发时清理该对象。

如果你的对象具有被终结清理或包含这样的非托管状态的任何其他对象的你在非托管状态做任何计算非托管状态,保证这些非托管计算后打电话到GC::KeepAlivethis。我现在倾向于将GC::KeepAlive附加到非托管计算对象的所有方法。

0

一个问题(刚刚拿到我):假设“析构函数只能执行一次”。由于析构函数是通过Dispose调用的,并且Dispose可能会被多次调用,所以对于C++/CLI这种假设(对于C++来说很好)并不适用。