2009-03-17 7 views
7

Per un mio progetto, sto scrivendo da zero alcuni contenitori STL (ho le mie ragioni). Poiché sto simulando così da vicino le funzionalità e le interfacce della STL, sto facendo del mio meglio per mantenere la politica "se ha lo stesso nome di un costrutto standard, sarà conforme allo standard il più possibile".std :: constructor allocuct/destroy vs. placement new/p-> ~ T()

Quindi, ovviamente, i miei contenitori accettano gli allocatori come parametro di modello, il che è molto piacevole in quanto consente di utilizzare alcuni schemi di allocazione personalizzati. Alla mia domanda.

L'interfaccia std::allocator separa l'allocazione della memoria dalla costruzione dell'oggetto. Allo stesso modo separa la deallocazione dalla distruzione. Questo ha senso dal momento che si ottiene la memoria da è più o meno irrilevante per costruire correttamente un oggetto in C++.

Quindi ci sono due funzioni costruzione/deallocazione che assomigliano a questo per l'implementazione predefinita (sollevato direttamente da un libro):

void construct(pointer p, const T& val) { new(p) T(val); } 
void destroy(pointer p)     { p->~T(); } 

come si può vedere costruire chiama semplicemente nuova collocazione e distruggere chiama semplicemente il distruttore .

C'è qualche motivo per utilizzare questi semplicemente usando la sintassi del nuovo e del posizionamento? un allocatore "corretto" può implementarli in un altro modo? O sono garantito che tutte le implementazioni degli allocatori che sono conformi allo standard avranno dei metodi di costruzione/distruzione implementati in questo modo?

Più precisamente, è sicuro dire che posso sempre usare std::uninitialized_copy e std::uninitialized_fill per la costruzione degli elementi dei miei contenitori?

Grazie.

risposta

8

L'allocatore può aggiungere dichiarazioni di registrazione prima e dopo la costruzione/distruzione, o qualsiasi altro effetto collaterale che si prenda cura di fare.

Naturalmente la costruzione effettiva deve avvenire chiamando nuova collocazione e il distruttore, ma non dice nel libro delle regole che nient'altro deve avvenire nel costrutto funzioni/distruggere

+1

sì, questo è un buon punto, potrebbe essere un buon aggancio per la registrazione "post-allocazione/pre-costruzione" o il monitoraggio di memleak. –

+1

Questa risposta è corretta ma un po 'fuorviante. Gli effetti collaterali come la registrazione sono in realtà abbastanza difficili da fare con la corretta sicurezza delle eccezioni. Più spesso la personalizzazione è regolando la nuova espressione incorporata, ad es. argomenti del costruttore Vedi https://groups.google.com/a/isocpp.org/d/topic/std-discussion/yZLnYy_y2z0/discussion – Potatoswatter

2

Questo è solo per nascondere i dettagli di allocazione in un metodo. cioè, stiamo fornendo le API per la costruzione e la distruzione, in futuro possiamo cambiare l'implementazione. Ora stiamo usando il posizionamento nuovo per allocare la memoria, in futuro se vogliamo cambiare l'allocazione, dobbiamo solo cambiare questi due metodi.

+0

sì, posso essere d'accordo con quello. Ma sono curioso di sapere se lo standard consente loro di cambiare? (specialmente con gli allocatori personalizzati che non dobbiamo aspettare un nuovo std per ...). –

+0

'allocator :: construct' non ha assolutamente nulla a che fare con l'allocazione, e dato che tutti gli allocatori (ora) sono allocati, non riesco a immaginare perché farebbero' costruire '' qualcos'altro ' –