2010-05-02 17 views
14

ho notato che ci sono due modi per creare oggetti C++:Creazione di C++ oggetti

BTree *btree = new BTree; 

e

BTree btree; 

Da quello che posso dire, l'unica differenza è nel modo in cui gli oggetti di classe si accede (. vs. -> operatore) e quando viene utilizzato il primo modo, gli interi privati ​​vengono inizializzati su 0.

Qual è il modo migliore e qual è la differenza?

Come fai a sapere quando utilizzare l'uno o l'altro?

+3

Vedere qui per informazioni su heap e stack: http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap, http://stackoverflow.com/questions/ 408670/stack-static-and-heap-in-c –

risposta

0

Bene, vengono memorizzati in regioni di memoria abbastanza diverse.

Ecco una buona lettura. Heap and Stack

+0

So un po 'di heap e stack. Perché dovrei preoccuparmi di dove viene messo? Quando lo voglio nell'heap e quando lo voglio nello stack? – neuromancer

+0

Lo stack è limitato in un'applicazione. L'heap non ha limiti (spazio di memoria virtuale). Lo stack è inoltre limitato all'ambito della variabile. L'heap consente di passare la struttura indipendentemente dall'ambito. –

+0

Questa affermazione è errata. Si prega di non ignorare la memoria statica. Per esempio.un'istruzione 'BTree btree;' in ambito globale (o spazio dei nomi) crea l'oggetto nella memoria statica, che può avere molto senso, specialmente in ambienti con vincoli di memoria (tutti quei linguaggi gestiti automaticamente come Java * cough * sembravano ciechi noi..). – Frunsi

5

Il primo modulo crea l'oggetto sull'heap mentre il secondo lo crea nello stack.

Il secondo da verrà distrutto quando la funzione è finita in esecuzione. Il primo rimarrà in vita fino a quando non viene eliminato in modo specifico.

Il secondo modulo è il migliore se si desidera utilizzare solo l'oggetto nell'ambito corrente. Non devi preoccuparti di sbarazzartene perché sarà fatto per te. Si noti inoltre che alcune librerie non funzionano se vengono create classi nello stack.

Se l'oggetto deve sopravvivere alla funzione, il nuovo modulo è un'opzione migliore.

32

Due differenze:

  • creano gli oggetti in diverse parti della memoria (heap vs stack)

  • la durata oggetto è differente: Nel primo caso, il codice gestisce la allocazione di memoria esplicitamente, e deve anche gestire la deallocazione esplicitamente (utilizzando delete/delete []).

    Nel secondo caso, l'oggetto si rilascia automaticamente al termine della sua portata racchiude (o con un metodo, un blocco annidato all'interno di un metodo o una classe)

Quale si usa dipende principalmente sulla durata dell'oggetto (se deve sopravvivere al metodo in cui è stato creato o meno).

+1

+1, vorrei solo aggiungere una prima e semplice regola empirica: preferire l'allocazione automatica, utilizzare l'allocazione esplicita quando richiesto, ad es. un esempio BAD: 'void foo() {BTree * btree = new BTree; btree-> DoSomething(); elimina btree; } ' – Frunsi

+0

Se l'oggetto è dichiarato in main, sarà automaticamente rilasciato al momento dell'uscita principale per entrambi i metodi? – neuromancer

+0

Un oggetto assegnato all'heap (che utilizza 'new') che non viene eliminato prima della fine del programma non sarà" deallocato "di per sé. Ad esempio, il suo distruttore non sarà chiamato come il programma sta finendo. Tuttavia, la memoria utilizzata dall'oggetto verrà restituita al sistema operativo. Non c'è modo che un programma in esecuzione su un sistema operativo moderno possa continuare a consumare memoria dopo che è uscito, a prescindere da quanto perdite. –

2

La distinzione di alto livello è durata dell'oggetto. Ad esempio, se stavi scrivendo un videogioco, dovresti assegnare gli oggetti corrispondenti ai mostri sullo heap, tramite new. In questo modo, l'oggetto sottostante del mostro vive esattamente come il mostro, il che è inconoscibile quando scrivi il programma. Quando il giocatore uccide il mostro, il tuo codice può distruggere l'oggetto mostro usando delete.

Un contatore punteggio totale, d'altra parte, si utilizzerà l'altro modulo, perché si sa per quanto tempo si vuole che il contatore rimanga intorno (presumibilmente, finché il gioco è in esecuzione!).Mettendo quella forma nella "portata globale", al di fuori di qualsiasi corpo di funzione, essa verrebbe allocata staticamente, come parte del binario del programma stesso.

Infine, se si dovesse calcolare la somma di una serie, in questo modo:

int mysum(int* arr, int len) { 
    int sum = 0; 
    for (int i = 0; i < len; ++i) { sum += arr[i] } 
    return sum; 
} 

la variabile sum è allocato sullo stack, che è fondamentalmente ciò che si vuole: una variabile temporanea che non si devi esplicitamente deallocare, e che è solo intorno a quando quella funzione è effettivamente in esecuzione.

3

Un'altra differenza tra questi due moduli è il momento in cui viene allocata la memoria per tali oggetti. Il modulo BTree bTree; assegna l'allocazione statica la cui assegnazione viene eseguita in fase di compilazione, ovvero il compilatore organizzerà lo spazio di memoria per questo oggetto in memoria durante l'esecuzione. Mentre, l'allocazione per BTree *pbTree = new BTree, la presunta allocazione dinamica - si esegue in fase di runtime - cioè il momory verrà assegnato solo quando il programma in esecuzione raggiungerà questo punto.

In questa situazione, la differenza tra allocazione statica e dinamica non è evidente. Si consideri la circostanza seguente in cui è necessario allocare spazio di memoria per un array intero, ma il numero di elementi può essere determinato solo in fase di esecuzione, cioè possiamo conoscere solo lo spazio di memoria esatto consumato dall'array dopo l'avvio del programma.

// in this function, we want to return a copy of the parameter array 
int *array_cpy(int *arr, int num){ 
    int *copy = new int[ num ]; 

    int i; 
    for(i = 0; i < num; i++){ 
     copy[ i ] = arr[ i ]; 
    } 

    return copy; 
} 

Ecco la definizione int copy[ num ]; non è opportuno, uno dei motivi è per quello che ho detto sopra, l'altro è la durata del copy sopravvivono funzione. Tuttavia, dato VLA è permesso nelle specifiche del linguaggio recente, la seconda ragione è la chiave per questo problema.

3

Nella scelta tra se è necessario impilare o archiviare allocare memoria, è necessario scavare un po 'nelle differenze tra i due.

Sì, la memoria di stack ha il vantaggio di essere deallocata automaticamente quando esce dal campo di applicazione, anche se lo stesso può essere ottenuto con i puntatori intelligenti e l'allocazione dell'heap. Più importanti sono le ragioni alla base del perché questo accade.

Prestazioni: La memoria dello stack viene eliminata automaticamente poiché comporta semplicemente lo spostamento di un puntatore dello stack quando la memoria esce dall'ambito. Per questo motivo, l'allocazione e la deallocazione della memoria dello stack sono molto più veloci della memoria heap.

Durata memoria: La memoria allocata di heap è disponibile oltre l'ambito della funzione di allocazione. Stack non lo è. Seguendo il ragionamento sulla regolazione del puntatore dello stack sopra, una volta che la memoria è stata deallocata, è gratuita e molto probabilmente verrà sovrascritta per l'allocazione dello stack successiva.

In breve, utilizzare la memoria dello stack quando l'allocazione è temporanea, in particolare se è necessario allocare ripetutamente e le prestazioni sono importanti. Utilizzare la memoria heap quando l'oggetto deve esistere oltre il metodo di allocazione.

Problemi correlati