C++ cli 我应该在C+中使用C#objects的引用还是实例+/CLI类? 在托管C++类中,我应该使用在另一个库中实现的C类的引用或实例吗?< /P>
考虑这个例子:C++ cli 我应该在C+中使用C#objects的引用还是实例+/CLI类? 在托管C++类中,我应该使用在另一个库中实现的C类的引用或实例吗?< /P>,c++-cli,C++ Cli,考虑这个例子: // MyManagedClass.h #pragma once using namespace System::Collections::Generic; using namespace My::Namespace::MyCSharpLib; namespace My::Namespace::MyManagedLib { public ref class MyManagedClass { public: MyCSharpClass m
// MyManagedClass.h
#pragma once
using namespace System::Collections::Generic;
using namespace My::Namespace::MyCSharpLib;
namespace My::Namespace::MyManagedLib
{
public ref class MyManagedClass
{
public:
MyCSharpClass myInst; // i have an instance!
MyCSharpClass ^myRef; // need to do gcnew
List<MyCSharpClass ^> listInst; // i have an instance!
List<MyCSharpClass ^> ^listRef; // need to do gcnew
};
}
我的直觉告诉我应该使用
myRef
和listRef
,因为如果这是在C#中实现的,我就会这样做。但是为什么我可以直接实例化MyCSharpClass
的实例呢?这样做的后果是什么?如果我的类只有一个MyCSharpClass
对象的集合,那么直接初始化该集合是否有害?C++/CLI有一个名为的功能,当您将引用类型成员声明为值类型(MyCSharpClass myInst;
)时,将使用该功能
gcnew
仍在被调用,但您看不到此代码,因为编译器将自动将其注入默认构造函数。请注意,它还将生成代码来处置myInst
下面是编译器将为您的类发出的MSIL的(伪)C++/CLI代码等价物:
构造函数:
MyManagedClass()
{
myInst = gcnew MyCSharpClass();
}
void Dispose(bool dispose)
{
if (dispose)
{
try
{
this->~MyManagedClass();
}
finally
{
delete myInst;
}
}
}
处置:
MyManagedClass()
{
myInst = gcnew MyCSharpClass();
}
void Dispose(bool dispose)
{
if (dispose)
{
try
{
this->~MyManagedClass();
}
finally
{
delete myInst;
}
}
}
编辑:
关于您关于反响的问题:使用gcnew
手动分配意味着当您的MyManagedClass
对象死亡时,myRef
指向的对象仍将挂起,直到垃圾收集器将其清除;而通过使用堆栈语义,您可以更确定地控制对象生命周期,而无需自己编写Dispose
方法
这还意味着,在使用堆栈语义时,您必须小心与谁共享对象…顺便说一句,如果您打算将C++/CLI用于除琐碎工作以外的任何工作,我建议您尝试使用Nishant Sivakumar的“C++/CLI in Action”。这是一个很好的语言功能参考,也将帮助您避免陷阱。谢谢!这让我想到了其他事情。经过一些测试,我了解到
driver.cs
中没有mmc.myInst
。此外,只有当MyCSharpClass
具有默认构造函数时,才会编译该类。“生成代码以解除分配myInst”不,它不会。释放仍由垃圾收集器管理。如果对象实现了IDisposable
,它将自动调用Dispose
。C++/CLI堆栈语义是使用块的C#的一个(到目前为止更强大)版本。C++/CLI中的
删除不是释放。这是对目标对象调用Dispose
(在安全地强制转换为IDisposable
之后)的一个更好的调用。尽管编辑段落仍然错误地指出,在使用堆栈语义时,垃圾收集器不控制对象生存期。在堆栈语义对象超出范围后,它就被处理掉了(所以大部分是无用的),但它实际上还没有死。根据.NET规则,您至少仍然可以对其调用Dispose
,并且某些对象可能允许在Dispose之后执行其他操作。正如您所说,通过“共享”对象而进行的引用不是随意的或悬空的指针,尽管使用它们可能会给您带来ObjectDisposedException
。