Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/visual-studio-code/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
困惑:c+中c#类的实例创建+;_C#_.net_C++_Stack_Instantiation - Fatal编程技术网

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

困惑:c+中c#类的实例创建+;,c#,.net,c++,stack,instantiation,C#,.net,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();

假设
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库的引用已添加到项目中,并且已做出相应的使用声明

据我所知,这是与前面的C#示例完全相同的C++/CLI(浓缩成一行,这不是我感兴趣的点)。对的(对不起,我不熟悉这个话题)

<>在C++中,也

someClass cpp_cauto;              // in C++ declaration implies instantiation
int i = cpp_cauto.doSomething(); 
是有效的语法。出于好奇,我今天试了这个。一位同事回头看了看我,打赌它甚至不会编译。他会输的。(这仍然是C#assembly中的类)。实际上,它还产生与前面示例中的代码相同的结果
i

也很漂亮,但是,嗯,到底是什么,这里创造了什么?我的第一个猜测是,.Net在我背后动态地在gc堆上创建了一个实例,
cpp_auto
是这个对象的某种包装器,在语法上就像class
someClass
的实例。但后来我找到了这一页

这个页面似乎告诉我,(至少,如果一个类是C++类)<代码> CPPUAuth/Obj>实际上是在堆栈上创建的,据我所知,这将是经典C++中的相同行为。还有一些你在C#中做不到的事情(你做不到,是吗?)。我想知道的是:来自C#assembly的实例是否也在堆栈上创建?在C++中,你可以用堆栈上的类实例来生成.NET二进制文件吗?这是否可能会给你带来性能增益:-)

亲切问候,

托马斯详细解释了这一点:

C++/CLI允许对引用类型使用堆栈语义。这意味着您可以使用为在堆栈上分配对象而保留的语法引入引用类型。编译器将提供给您的C++语言所需的语义,并通过在托管堆上实际分配对象来满足CLR的要求。 基本上,它仍在对托管堆上的引用类型进行句柄处理,但在
IDisposable
实现超出范围时会自动调用
Dispose()

但是,对象实例仍然通过
gcnew
(放置在托管堆上)进行有效分配,并由垃圾收集器收集。下面也详细解释了这一点:

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


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

Ouch。所以我在没有意识到的情况下找到了答案。谢谢你给我指出这一点:-)@Thomas没问题。这是一个很大的页面-您必须知道在那里查找什么才能找到关于编译器技巧的讨论;)再次感谢,但你看,这并不是因为这是一个大页面。关键是,只有在你向我指出引文确实回答了我的问题之后,我才理解引文。但也许这只是初学者的无知。当然,无知就是幸福:-)