2010-12-31 14 views
16

Cosa succede quando si ha il seguente codice:C++ puntatore portata

void makeItHappen() 
{ 
    char* text = "Hello, world"; 
} 

Does text uscire di portata e ottenere automaticamente cancellati o lo fa rimanere nella memoria?

E per quanto riguarda il seguente esempio:

class SomeClass 
{ 
    public: 
     SomeClass(); 
     ~SomeClass(); 
}; 

SomeClass::SomeClass() { } 
SomeClass::~SomeClass() 
{ 
    std::cout << "Destroyed?" << std::endl; 
} 

int main() 
{ 
    SomeClass* someClass = new SomeClass(); 
    return 0; 
} // What happend to someClass? 

fa la stessa cosa avviene qui?

Grazie!

risposta

22
char* text = "Hello, world"; 

Qui una variabile automatica (un puntatore) viene creato nella pila e impostato per indicare un valore in costante memoria, che significa:

  • la stringa letterale "" esiste attraverso la l'intera esecuzione del programma.
  • non si è responsabili per "allocazione" o "liberazione" it
  • non è possibile modificarlo. Se vuoi cambiarlo, devi allocare un po 'di "memoria non costante" e copiarlo lì.

Quando il puntatore esce dall'oscilloscopio, il puntatore della memoria stessa (4 byte) viene liberato e la stringa si trova ancora nello stesso punto, la memoria costante.

Per quest'ultimo:

SomeClass* someClass = new SomeClass(); 

Poi someClass puntatore sarà anche liberata quando passa nell'ambito (poiché il puntatore stesso è in pila troppo, solo nel primo esempio) ... ma non l'oggetto!

La parola chiave new fondamentalmente significa che si alloca po 'di memoria per l'oggetto su libero negozio - e sei responsabile per la chiamata delete qualche tempo al fine di liberare quella memoria.

+0

@Kos: questo significa che il numero 2 di 'int x = 2;' esiste anche attraverso l'intera esecuzione del programma? –

+1

La differenza è che il numero 2 non ha bisogno di avere un indirizzo in memoria, e la stringa lo fa (come viene puntato dal puntatore). * (Questo numero 2 esiste in qualche parte nella sezione di codice della tua memoria, a cui non hai mai bisogno di accedere direttamente, perché è, beh, il codice, non i dati.) * – Kos

+0

@Kos Grazie per un'ottima risposta ! Ma, che senso ha mantenere "Hello, world" 'in memoria? – Kevin

11

Does text andare fuori del campo di applicazione

Sì! È locale per la funzione makeItHappen() e quando la funzione restituisce non è più possibile. Tuttavia, il valore letterale stringa puntato a "Hello, world"; ha una durata di archiviazione statica e viene memorizzato nella sezione di sola lettura della memoria.

E per quanto riguarda il seguente esempio:

......
fa la stessa cosa si verifica qui?

Il secondo esempio di codice perde memoria.

SomeClass* someClass = new SomeClass();

someClass è locale per main() così quando ritorna principali essendo una variabile automatica viene distrutta. Tuttavia l'oggetto puntato rimane in memoria e non c'è modo di liberarlo dopo il ritorno della funzione. È necessario scrivere esplicitamente delete someClass per deallocare correttamente la memoria.

+1

+1 "puntato a stringa letterale" Ciao, mondo "; ha durata di archiviazione statica" –

+0

Perdita di memoria perché non è stato eliminato l'oggetto creato. –

6

Il testo variabile esce dall'ambito (tuttavia la stringa letterale non viene eliminata).

Per gli oggetti allocati con nuovi (come il tuo SomeClass), è necessario eliminarli esplicitamente. Se vuoi che gli oggetti così assegnati vengano automaticamente cancellati, dai un'occhiata a boost smart pointers (std :: unique_ptr se il tuo compilatore è C++ 0x informato).

Questo eliminerà automaticamente l'oggetto assegnato quando il puntatore condiviso esce dall'ambito.

Il tuo codice sarebbe quindi simile a questa:

int main(int argv, char **argv) 
{ 
    boost::scoped_ptr<SomeClass> ptr(new SomeClass); 
    // the object is automatically deleted 
    return 0; 
} 

Nota: In questo particolare esempio, si potrebbe anche usare std :: auto_ptr (ma questo sarà obsoleta in C++ 0x).

Nota 2: come è stato sottolineato nei commenti da Kos, è in questo caso più appropriato utilizzare boost :: scoped_ptr o std :: unique_ptr (C++ 0x). La mia risposta ha usato prima boost :: shared_ptr, che è più appropriato se è necessario condividere la proprietà di un puntatore tra più classi, per esempio.

+0

Avrei +1 ... ma poi ho notato che hai menzionato i puntatori di conteggio dei riferimenti, quando lo strumento più appropriato è 'std :: unique_ptr' da C++ 0x /' boost :: scope_ptr'/'std: : auto_ptr'. Questi sono responsabili dell'eliminazione dell'oggetto quando il puntatore esce dall'ambito e esattamente per quello. – Kos

+0

@Kos: hai assolutamente ragione che in questo caso particolare unique_ptr è più appropriato. Farò una modifica ... – villintehaspam

+0

+1 poi. :) (è l'ultimo collegamento shared_ptr lasciato intenzionalmente?) – Kos

1

Nel primo esempio la stringa letterale è memorizzata nel segmento di dati del file eseguibile.
Nel secondo caso non è necessario chiamare delete (nel programma di esempio appena terminato) poiché alla chiusura del programma l'heap viene comunque liberato per il processo.
Nota che ci sono OS (come ho letto) che devi rilasciare in modo esplicito heap anche se il programma termina poiché non verrà ripulito al momento.
Ovviamente il programmatore è responsabile della gestione della memoria in C++ e gli oggetti creati su heap devono essere delete ed una volta non necessari.