困惑:在c++中创建c#类的实例

Confused: instance creation of c# class in c++

本文关键字:实例 创建 c++ 困惑      更新时间:2023-10-16

假设someClass是一个在c#中定义的类,具有某种方法int doSomething(void),为了简单起见,提供一个不带参数的构造函数。然后,在c#中,实例必须在gc堆上创建:

someClass c;                   // legit, but only a null pointer in C#
// c->doSomething()            // would not even compile. 
c = new someClass();           // now it points to an instance of someclass.
int i = c->doSomething();      

现在,如果someClass被编译成一些。net库,你也可以在c++/CLI中使用它:

someClass^ cpp_gcpointer = gcnew someClass();
int i = cpp_gcpointer->doSomething();

,简单!漂亮的!当然,这是假设对。net库的引用已经添加到项目中,并且已经做了相应的using声明。

这是我的理解,这是精确的c++/CLI等效于前面的c#示例(浓缩到一行,这不是我感兴趣的点)。正确吗?(对不起,我对这个话题不熟悉)

在c++中,同样

someClass cpp_cauto;              // in C++ declaration implies instantiation
int i = cpp_cauto.doSomething(); 

是有效的语法。出于好奇,我今天尝试了这个。我的一位同事在我身后看着我,愿意打赌它甚至无法编译。他会输掉打赌的。(这仍然是c#程序集中的类)。实际上,它也产生了与前面示例代码相同的结果i

也很漂亮,但是——嗯——它到底是什么,这里创建了什么?我的第一个大胆猜测是,在我背后,. net动态地在gc堆上创建了一个实例,而cpp_auto是这个对象的某种包装器,在语法上表现得像someClass类的实例。但后来我发现了这一页

http://msdn.microsoft.com/en-us/library/ms379617%28v=vs.80%29.aspx vs05cplus_topic2

这个页面似乎告诉我,(至少,如果someeclass是一个c++类)cpp_auto实际上是在堆栈上创建的,据我所知,这将是你在经典c++中得到的相同行为。这是你在c#中做不到的(你做不到,对吧?)我想知道的是:从c#程序集的实例也创建在堆栈上吗?你能否在c++中生成。net二进制文件,并在堆栈中创建类实例,而这在c#中是无法创建的?这可能会给你带来性能提升吗?

亲切的问候,托马斯

您引用的链接详细说明了这一点:

c++/CLI允许对引用类型使用堆栈语义。这意味着您可以使用为堆栈上的对象分配保留的语法引入引用类型。编译器将负责为您提供您期望从c++中获得的语义,并在幕后通过在托管堆上实际分配对象来满足CLR的要求。

基本上,它仍然对托管堆上的引用类型做一个句柄,但是当它超出IDisposable的范围时,它会自动调用Dispose()

但是,对象实例仍然通过gcnew有效地分配(放在托管堆上),并由垃圾收集器收集。这也有详细的解释:

当d超出作用域时,将调用其Dispose方法以允许释放其资源。同样,由于对象实际上是从托管堆中分配的,因此垃圾收集器将在自己的时间内负责释放它。

基本上,这些都是由编译器处理的,使代码看起来和工作起来像标准的c++堆栈分配类,但这实际上只是一个编译器的技巧。生成的IL代码仍然在执行托管堆分配。