2010-08-14 7 views
54

Come posso realloc in C++? Sembra che manchi dalla lingua: c'è lo new e lo delete ma non lo resize!Come si "realloc" in C++?

Ho bisogno perché il mio programma legge più dati, ho bisogno di riallocare il buffer per tenerlo. Non penso che il delete il vecchio puntatore e lo new un nuovo, più grande, sia l'opzione giusta.

+7

Stroustrup ha risposto a questo molto tempo fa, vedere: http://www2.research.att.com/~bs/bs_faq2.html#renew (Questo è un buon inizio se siete nuovi al C++ insieme alle FAQ di C++ di Cline.) – dirkgently

+4

La risposta a cui fa riferimento @dirkgently è ora disponibile all'indirizzo: http://www.stroustrup.com/bs_faq2.html#renew e le domande frequenti di Cline fanno ora parte delle super FAQ: https://isocpp.org/faq – maxschlepzig

risposta

35

Usa :: std :: vector!

Type* t = (Type*)malloc(sizeof(Type)*n) 
memset(t, 0, sizeof(Type)*m) 

diventa

::std::vector<Type> t(n, 0); 

Poi

t = (Type*)realloc(t, sizeof(Type) * n2); 

diventa

t.resize(n2); 

Se si desidera passare il puntatore in funzione, invece di

012.
Foo(t) 

uso

Foo(&t[0]) 

È assolutamente codice corretto C++, perché vettore è un C-array intelligente.

+1

Non dovrebbe essere memset la linea memset (t, 0, sizeof (T) * n) ;? n invece di m? – anthom

+1

@anthom si. dovrebbe essere davvero 'Type * t = static_cast (malloc (n * sizeof * t));' –

+0

Con C++ 11 uno ora userebbe 't.data()' invece di '& t [0]' – knedlsepp

39

L'opzione giusta è probabilmente quella di utilizzare un contenitore che fa il lavoro per voi, come std::vector.

new e non possono ridimensionare, perché allocano memoria sufficiente per contenere un oggetto del tipo specificato. La dimensione di un determinato tipo non cambierà mai. Ci sono new[] e delete[] ma non c'è quasi mai un motivo per usarli.

Cosa realloc fa in C è probabile che sia solo un malloc, memcpy e free, in ogni caso, anche se i gestori di memoria sono autorizzati a fare qualcosa di intelligente se c'è abbastanza memoria libera contigua a disposizione.

+0

Quindi quale sarebbe il modo giusto per implementare un buffer in crescita in C++? Attualmente ho 'char * buf = (char *) malloc (size)', poi quando diventa troppo piccolo faccio 'buf = realloc (size + more_size); size + = more_size'. Come posso farlo con il vettore? – bodacydo

+6

@bodacydo: non implementare il buffer in crescita, basta usare 'std :: vector' - crescerà automaticamente quando necessario e potrai pre-allocare memoria se lo desideri (' reserve() '). – sharptooth

+3

Usa std :: vector . Ecco a cosa serve In C++, non vi è alcun motivo per utilizzare new/delete/new []/delete [] se non si scrivono esplicitamente classi di gestione delle risorse. – Puppy

29

Il ridimensionamento in C++ è scomodo a causa della potenziale necessità di chiamare costruttori e distruttori.

Non credo che ci sia una ragione fondamentale per cui in C++ non si poteva avere un operatore di resize[] di andare con new[] e delete[], che ha fatto qualcosa di simile a questo:

newbuf = new Type[newsize]; 
std::copy_n(oldbuf, std::min(oldsize, newsize), newbuf); 
delete[] oldbuf; 
return newbuf; 

Ovviamente oldsize verrebbero recuperati da una posizione segreta, lo stesso è in delete[] e Type verrebbe dal tipo dell'operando. resize[] non riuscirebbe dove il Tipo non è copiabile, il che è corretto, dal momento che tali oggetti semplicemente non possono essere trasferiti. Infine, il codice sopra predefinito costruisce gli oggetti prima di assegnarli, cosa che non si vorrebbe come comportamento effettivo.

C'è una possibile ottimizzazione in cui newsize <= oldsize, per chiamare i distruttori per gli oggetti "oltre la fine" del nuovo array ensmallened e non fare nient'altro.Lo standard dovrebbe definire se questa ottimizzazione è richiesta (come quando si è resize() un vettore), consentita ma non specificata, consentita ma dipendente dall'implementazione o proibita.

La domanda che dovresti poi porsi è, "è effettivamente utile fornire questo, dato che lo fa anche vector, ed è progettato specificamente per fornire un contenitore resize-resable (di memoria contigua - quel requisito omesso in C++ 98 ma risolto in C++ 03) che è un adattamento migliore degli array con i modi C++ di fare le cose? "

Penso che la risposta sia ampiamente considerata "no". Se si desidera eseguire buffer ridimensionabili in modalità C, utilizzare malloc/free/realloc, disponibili in C++. Se si desidera eseguire buffer ridimensionabili in modo C++, utilizzare un vettore (o deque, se non si ha effettivamente bisogno di spazio di archiviazione contiguo). Non provare a mescolare i due utilizzando new[] per i buffer raw, a meno che non si stia implementando un contenitore di tipo vettoriale.

-4

provare qualcosa di simile:

typedef struct Board 
{ 
    string name; 
    int size = 0; 
}; 

typedef struct tagRDATA 
{ 
    vector <Board> myBoards(255); 

    // Board DataBoard[255]; 
    int SelectedBoard; 

} RUNDATA; 

vettore si lamenterà. Ecco perché esistono ancora array, malloc e nuovi.

+4

No, non è per questo. E non vedo come questo risponda alla domanda in alcun modo. O perché stai usando 'typedef' ovunque come se stessi scrivendo C. –