Domanda

In C le funzioni di gestione della memoria standard sono malloc(), realloc() e free(). Tuttavia, C ++ stdlib allocatori solo parallelo due: non c'è alcuna funzione riallocazione. Naturalmente, non sarebbe possibile fare esattamente lo stesso come realloc(), perché semplicemente copiando memoria non è appropriato per i tipi non aggregate. Ma ci sarebbe un problema, per esempio, questa funzione:

bool reallocate (pointer ptr, size_type num_now, size_type num_requested);

dove

  • ptr viene preventivamente allocata con lo stesso allocatore per gli oggetti num_now;
  • num_requested> = num_now;

e la semantica come segue:

  • se allocatore può espandersi in blocco di memoria a ptr dalla dimensione degli oggetti num_now agli oggetti num_requested, lo fa (lasciando memoria aggiuntiva inizializzato) e ritorna true;
  • altrimenti non fa nulla e ritorna false.

Certo, questo non è molto semplice, ma allocatori, a quanto mi risulta, sono per lo più significava per contenitori e container codice di solito è complicato già.

Dato un tale funzione, std::vector, per esempio, potrebbe crescere come segue (pseudocodice):

if (allocator.reallocate (buffer, capacity, new_capacity))
  capacity = new_capacity;     // That's all we need to do
else
  ...   // Do the standard reallocation by using a different buffer,
        // copying data and freeing the current one

Allocators che sono incapaci di cambiare la dimensione della memoria del tutto potrebbe semplicemente implementare tale funzione return false; incondizionata.

ci sono così pochi implementazione allocatore riallocazione-capable che non sarebbe valsa la pena di preoccuparsi? O ci sono alcuni problemi che ho trascurato?

È stato utile?

Soluzione

Da: http://www.sgi.com/tech/stl/alloc.html

  

Questa è probabilmente la più discutibile   progettare decisione. Avrebbe   stato probabilmente un po 'più utile   fornire una versione di riassegna tale   sia cambiato la dimensione del   oggetto esistente senza copiare o   NULL restituito. Questo avrebbe reso   direttamente utile per oggetti con copia   costruttori. Sarebbe anche avere   la copia inutile evitata nei casi   in cui l'oggetto originale non aveva   stato completamente riempito.

     

Purtroppo, ciò avrebbe   uso vietato di realloc dalla C   biblioteca. Questo a sua volta avrebbe aggiunto   la complessità di molti allocatore   implementazioni, e avrebbero fatto   interazione con memoria debugging   strumenti più difficile. Così abbiamo deciso   contro questa alternativa.

Altri suggerimenti

Questo è in realtà un difetto di progettazione che Alexandrescu sottolinea con i ripartitori standard (non operator new [] / delete [] Ma quali erano originariamente i ripartitori STL utilizzati per implementare std :: vector, per esempio).

Un realloc può verificarsi significativamente più veloce di una malloc, memcpy, e gratuito. Tuttavia, mentre il blocco di memoria effettivo può essere ridimensionato, può anche spostare la memoria in una nuova posizione. In quest'ultimo caso, se il blocco di memoria costituito da non-POD, tutti gli oggetti dovranno essere distrutti e copia-costruito dopo il realloc.

La cosa principale della libreria standard ha bisogno di ospitare questo come un possibilità è una funzione RIALLOCAZIONE come parte dell'interfaccia pubblica del allocatore standard. Una classe come std :: vector potrebbe certamente usarlo anche se l'implementazione di default è a malloc il blocco appena dimensioni e liberare il vecchio. Avrebbe bisogno di essere una funzione che è capace di distruggere e copia-costruire gli oggetti nella memoria però, non può trattare la memoria in maniera opaca se questo fatto. C'è c'è un po 'di complessità della questione e richiederebbe un po' più di lavoro modello che può essere il motivo per cui è stato omesso dalla libreria standard.

std :: vector <...> :: riserva non è sufficiente: si rivolge un caso diverso in cui la dimensione del contenitore può essere anticipata. Per gli elenchi veramente di dimensioni variabili, una soluzione realloc potrebbe fare contenitori contigui come std :: vector molto più veloce, soprattutto se si può trattare casi realloc in cui il blocco di memoria è stata ridimensionata con successo senza essere spostati, nel qual caso si può omettere chiamando copia costruttori e distruttori per gli oggetti in memoria.

Quello che stai chiedendo è essenzialmente ciò che vector::reserve fa. Senza la semantica di movimento per gli oggetti, non c'è modo per la memoria RIALLOCAZIONE e spostare gli oggetti intorno senza fare una copia e distruggere.

A causa della object oriented natura di C ++, e l'inclusione di vari tipi di contenitori standard, Credo sia semplicemente che meno attenzione è stata posta sulla gestione della memoria direzione rispetto a C. Sono d'accordo che ci sono casi in cui un realloc () sarebbe utile, ma la pressione per rimediare a questo è minimo, come quasi tutta la funzionalità risultante può essere ottenuto utilizzando contenitori invece.

Credo che questo è una delle cose in cui Dio è andato storto, ma ero troppo pigro per scrivere al comitato per le norme.

Non ci avrebbe dovuto essere un realloc per le allocazioni di array:

p = renew(p) [128];

o qualcosa del genere.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top