Смущает: создание экземпляра класса c # в c ++ - PullRequest
16 голосов
/ 23 ноября 2011

Предположим, 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 ++ / 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

Эта страница, кажется, говорит мне, что (по крайней мере, если someClass был бы классом C ++) cpp_auto фактически создается в стеке, что, насколько я знаю, будет таким же поведением, как и в классическом C ++. И то, что вы не можете сделать в C # (вы не можете, не так ли?). Что я хотел бы знать: экземпляр из сборки C # также создается в стеке? Можете ли вы создавать .Net двоичные файлы в C ++ с экземплярами классов в стеке, которые вы не можете создать в C #? И может ли это даже дать вам прирост производительности :-)?

С уважением,

Thomas

1 Ответ

12 голосов
/ 23 ноября 2011

Ссылка , на которую вы ссылались , объясняет это подробно:

C ++ / CLI позволяет вам использовать семантику стека с ссылочными типами.Это означает, что вы можете ввести ссылочный тип, используя синтаксис, зарезервированный для размещения объектов в стеке.Компилятор позаботится о том, чтобы предоставить вам семантику, которую вы ожидаете от C ++, и под прикрытием отвечает требованиям CLR, фактически распределяя объект в управляемой куче.

По сути, это все ещесоздает дескриптор ссылочного типа в управляемой куче, но автоматически вызывает Dispose() в IDisposable реализациях, когда он выходит за пределы вашей области.

Однако экземпляр объекта по-прежнему эффективно выделяется через gcnew (помещается в управляемую кучу) и собирается сборщиком мусора.Это также объясняется подробно:

Когда d выходит из области видимости, вызывается его метод Dispose, чтобы разрешить освобождение его ресурсов.Опять же, поскольку объект фактически выделяется из управляемой кучи, сборщик мусора позаботится о его освобождении в свое время.

По сути, все это обрабатывается компилятором, чтобы код выглядели работают как стандартные классы, выделенные из стека C ++, но на самом деле это просто трюк с компилятором.Полученный код IL по-прежнему выполняет выделение управляемой кучи.

...