2010-06-03 4 views
6

Okay la domanda previous ha risposto chiaramente, ma ho scoperto un altro problema.C++ nuovo & delete e stringa e funzioni

Cosa succede se fare:

char *test(int ran){ 
    char *ret = new char[ran]; 
    // process... 
    return ret; 
} 

e quindi eseguirlo:

for(int i = 0; i < 100000000; i++){ 
    string str = test(rand()%10000000+10000000); 
    // process... 

    // no need to delete str anymore? string destructor does it for me here? 
} 

Così, dopo la conversione del char * a stringa, non devo preoccuparsi per la cancellazione più?

Edit: Come risposta, devo delete[] ogni new[] chiamata, ma nel mio caso la sua non è possibile in quanto il puntatore si è perso, quindi la domanda è: come faccio a convertire char a stringa correttamente?

+0

Ri: Modifica ... perdere il puntatore (come per la mia risposta di seguito) o (meglio ancora) non 'new' il puntatore, basta usare' std :: string' per contenere la stringa. Perché vuoi fare l'allocazione di memoria da solo? – Johnsyweb

risposta

9

Qui non sta convertendo il char* ad un [std::]string, ma copia il char* ad un [std::]string.

Come regola generale, per ogni new dovrebbe esserci un delete.

In questo caso, è necessario memorizzare una copia del puntatore e delete quando il gioco è fatto:

char* temp = test(rand()%10000000+10000000); 
string str = temp; 
delete[] temp; 
+0

Quindi, come faccio a convertire correttamente il char in stringa? – Newbie

+0

Immagino che quando ti è stato detto di convertire 'char *' in 'std :: string', cosa si intendeva che dovresti ** usare **' std :: string' piuttosto che 'char *', non per * convert * programatically. – Johnsyweb

+0

Potrebbe esserci un modo più semplice per farlo? come una sorta di funzione o qualcosa del genere, quindi basterebbe una sola riga di codice? – Newbie

2

Sì, sì.

Se si utilizza linux/os x, guardare in qualcosa di simile a valgrind che può aiutare con la memoria emette

È possibile modificare la funzione di test in modo che restituisca un string invece di char *, in questo modo è possibile delete [] ret nella funzione di test.

OPPURE è possibile utilizzare una stringa anche nel test e non preoccuparsi di nuovo/eliminazione.

+0

Quindi devo usare: delete [] str; ? – Newbie

+0

No, str è un oggetto proprio. In questo caso, hai perso il puntatore al nuovo char [] che hai assegnato e quindi avrà una perdita di memoria dal momento che non puoi cancellarlo. –

3

Lei sembra essere sotto l'impresison che il superamento di un char* in std :: la stringa trasferisce la proprietà della memoria allocata. In effetti fa solo una copia.

Il modo più semplice per risolverlo è utilizzare semplicemente una stringa std :: string in tutta l'intera funzione e restituirla direttamente.

std::string test(int ran){ 
    std::string ret; 
    ret.resize(ran - 1); // If accessing by individual character, or not if using the entire string at once. 
    // process... (omit adding the null terminator) 
    return ret; 
} 
+0

+1 per saltare la fase intermedia della creazione di un char *. Detto questo, il codice di esempio manca un nome ... –

2

È must chiamata delete per ogni new altrimenti si perderà la memoria. Nel caso in cui hai indicato che stai lanciando il puntatore, se devi lasciare la funzione come restituendo un char* allora dovrai usare due linee per creare lo std::string in modo da poter conservare una copia dello char* su delete.

Una soluzione migliore sarebbe la riscrittura della funzione test() per restituire direttamente un std::string.

2

Hai bisogno di fare qualcosa di simile:

for(int i = 0; i < 100000000; i++){ 
    int length = rand()%10000000+10000000; 
    char* tmp = test(length); 
    string str(tmp); 
    delete[length] tmp; 
} 

Questo cancella il char-array allocato correttamente.

A proposito, si dovrebbe sempre terminare a zero una stringa se la si crea in questo modo (cioè all'interno della funzione test), altrimenti alcune funzioni possono facilmente "confondersi" e trattare i dati dietro la stringa come parte di esso, che nel migliore dei casi blocca la tua applicazione e, nel peggiore dei casi, crea un buffer overflow silenzioso che porta a un comportamento indefinito in un momento successivo, che è l'ultimo incubo di debug ...;)