2011-11-23 1 views
16

Assumere someClass è una classe definita in C# con qualche metodo int doSomething(void) e, per semplicità, fornire un costruttore che non accetta argomenti. Poi, in C#, le istanze devono essere create sul mucchio gc:Confuso: creazione di istanza della classe C# in C++

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();  

Ora, se someClass è compilato in qualche libreria Net, è possibile utilizzarlo anche in C++/CLI:

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

Così facile! Nifty! Questo naturalmente presuppone che un riferimento alla libreria .Net sia stato aggiunto al progetto e che sia stata fatta una corrispondente dichiarazione di utilizzo.

È a mia conoscenza che questo è l'equivalente C++/CLI del precedente esempio C# (condensato su una singola riga, questo non è il punto che mi interessa). Corretta? (Scusate, sono nuovo al tema)

In C++, tuttavia, anche

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

è sintassi valida. Per curiosità, ci ho provato oggi. Un collega, che mi guardava alle spalle, era disposto a scommettere che non sarebbe stato nemmeno compilato. Avrebbe perso la scommessa. (Questa è ancora la classe dal gruppo C#). In realtà produce anche lo stesso risultato i come il codice degli esempi precedenti.

Nifty, anche, ma - uhmm - cosa è esattamente, cosa viene creato qui? La mia prima ipotesi è stata che dietro la mia schiena, .Net crea dinamicamente un'istanza sull'heap gc e è una specie di wrapper per questo oggetto, che si comporta in modo sintattico come un'istanza della classe someClass. Ma poi ho trovato questa pagina

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

Questa pagina sembra dirmi, che (almeno, se someClass fosse una classe C++) cpp_auto è in realtà creato nello stack, che, a mia conoscenza, sarebbe lo stesso comportamento che si ottiene nel classico C++. E qualcosa che non puoi fare in C# (non puoi, puoi?). Cosa mi piacerebbe sapere: l'istanza dall'assembly C# viene anche creata nello stack? Puoi produrre binari .Net in C++ con istanze di classe nello stack che non puoi creare in C#? E questo forse potrebbe anche darti un guadagno in perfomance :-)?

Cordiali saluti,

Thomas

risposta

12

Il link you referenced spiega in dettaglio:

C++/CLI permette di impiegare la semantica dello stack con i tipi di riferimento. Ciò significa che è possibile introdurre un tipo di riferimento utilizzando la sintassi riservata per l'allocazione degli oggetti nello stack. Il compilatore si prenderà cura di fornirti la semantica che ti aspetteresti da C++, e sotto le copertine soddisfi i requisiti del CLR assegnando effettivamente l'oggetto all'heap gestito.

In sostanza, è ancora facendo un handle per il tipo di riferimento sul mucchio gestito, ma chiede automaticamente Dispose() su IDisposable implementazioni quando va fuori portata per voi.

L'istanza dell'oggetto, tuttavia, viene ancora effettivamente allocata tramite gcnew (posizionata nell'heap gestito) e raccolta dal garbage collector. Anche questo è spiegato in dettaglio:

Quando d esce dall'ambito, verrà chiamato il suo metodo Dispose per consentire il rilascio delle sue risorse. Anche in questo caso, poiché l'oggetto viene effettivamente assegnato dall'heap gestito, il garbage collector si prenderà cura di liberarlo nel proprio tempo.

Fondamentalmente, questo è tutto gestito dal compilatore per rendere il codice aspetto e lavorare come standard di C++ impilare le classi assegnate, ma è davvero solo un trucco del compilatore. Il codice IL risultante sta ancora eseguendo allocazioni heap gestite.

+0

Ouch. Quindi ho trovato la risposta senza riconoscerla. Grazie per avermelo fatto notare :-) – Thomas

+0

@Thomas Nessun problema. È una pagina grande - devi sapere cosa cercare lì dentro per trovare la discussione sul trucco del compilatore;) –

+0

Grazie ancora, ma beh, vedi, non è perché è una pagina grande. Il punto è che capisco la citazione solo dopo che mi hai fatto notare che risponde alla mia domanda. Ma forse questa è solo l'ignoranza dei principianti. E poi, ovviamente, l'ignoranza è beatitudine :-) – Thomas