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

Tho*_*mas 16 .net c# c++ stack instantiation

假设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();      
Run Code Online (Sandbox Code Playgroud)

现在,如果someClass编译成一些.Net库,你也可以在C++/CLI中使用它:

someClass^ cpp_gcpointer = gcnew someClass();
int i = cpp_gcpointer->doSomething();
Run Code Online (Sandbox Code Playgroud)

那简单!漂亮!这当然假设已经将.Net库的引用添加到项目中并且已经进行了相应的使用声明.

我的理解是,这是前一个C#示例的精确C++/CLI等效(缩写为单行,这不是我感兴趣的点).正确?(对不起,我是这个话题的新手)

但是,在C++中也是如此

someClass cpp_cauto;              // in C++ declaration implies instantiation
int i = cpp_cauto.doSomething(); 
Run Code Online (Sandbox Code Playgroud)

是有效的语法.出于好奇,我今天试了这个.一位同事,看着我的肩膀,愿意打赌它甚至不会编译.他本可以输掉赌注.(这仍然是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二进制文件?这有可能甚至可以给你带来性能:-)?

亲切的问候,

托马斯

Ree*_*sey 12

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

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

基本上,它仍然使一个句柄托管堆上引用类型,但自动调用Dispose()IDisposable,当它超出范围为你实现.

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

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

基本上,这都是由编译器处理的,以使代码看起来像标准C++堆栈分配类一样工作,但它实际上只是一个编译技巧.生成的IL代码仍在进行托管堆分配.