假设someClass
是使用某种方法int doSomething(void)
在C#中定义的类,为简单起见,提供不带参数的构造函数。然后,在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库的引用添加到项目中并且已经进行了相应的使用声明。
据我所知,这是前一个C#示例的精确C ++ / CLI等效(缩写为单行,这不是我感兴趣的点)。正确? (对不起,我是这个话题的新手)
但是,在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
这个页面似乎告诉我,(至少,如果someClass是一个C ++类)cpp_auto
实际上是在堆栈上创建的,据我所知,这与你在经典C ++中的行为相同。而你在C#中做不到的事情(你做不到,可以吗?)。我想知道的是:C#程序集中的实例也是在堆栈上创建的吗?您是否可以在C ++中使用C#中无法创建的类实例生成.Net二进制文件?这有可能甚至可以给你带来性能:-)?
亲切的问候,
托马斯
答案 0 :(得分:12)
link you referenced详细解释了这一点:
C ++ / CLI允许您使用引用类型的堆栈语义。这意味着您可以使用保留用于在堆栈上分配对象的语法来引入引用类型。编译器将负责为您提供您期望从C ++获得的语义,并通过在托管堆上实际分配对象来满足CLR的要求。
基本上,它仍在处理托管堆上的引用类型,但在Dispose()
实现超出范围时自动调用IDisposable
。
但是,对象实例仍然通过gcnew
(放置在托管堆上)有效地分配并由垃圾收集器收集。这也将详细解释:
当d超出范围时,将调用其Dispose方法以允许其资源被释放。同样,由于对象实际上是从托管堆中分配的,因此垃圾收集器会在自己的时间内释放它。
基本上,这完全由编译器处理,使代码看起来像标准C ++堆栈分配类一样工作,但它实际上只是一个编译技巧。生成的IL代码仍在进行托管堆分配。