2013-05-03 11 views
24

Quindi stavo osservando le specifiche di std::vector e ho notato che reference typedef modificato da Allocator::reference in C++ 03 a value_type& in C++ 11. Sono rimasto sorpreso, quindi ho iniziato a guardare più a fondo.Perché viene disattivato Allocator :: reference?

In C++ 03 §20.1.5 [lib.allocator.requirements] c'è tavolo 32 in cui X::reference è definito come T& e X::const_reference è definito come T const&.

Tuttavia, in C++ 11 §17.6.3.5 [allocator.requirements] c'è la tabella 28 in cui mancano reference e const_reference.

Successivamente abbiamo aggiunto il codice 20.6.8 std::allocator_traits in C++ 11 che non include reference. Ma il §20.6.9 std::allocator fa.

Infine, c'è §23.2.1 [container.requirements.general] che definiscono X::reference essere "lvalue di T" e X::const_reference essere "Ivalue const T".

Così, Googled e trovato questo documento (1, 2) che si propone la rimozione di reference dai requisiti allocatore, ma non menziona alcuna logica dietro di esso. Ma c'è anche un LWG issue che si oppone al cambiamento.

Inoltre, ho trovato the interview with Alexander Stepanov in cui parla di come reference incapsula layout di memoria specifiche della macchina e Herb Sutter's post in cui parla di prendere puntatori a elementi contenitori, i requisiti di container e di come std::vector<bool> non è un contenitore.

Quindi, cosa ne pensi di tutto questo? reference è stato utile, è stato utile? In che modo i riferimenti "fantasiosi" rientrano nello standard? È una mossa audace eliminarli completamente, rendere più rigidi i requisiti del contenitore e deprecare std::vector<bool>?

+6

domanda ben ricercata – David

+0

No, non è molto audace. Interromperò la compilazione se qualcuno tenta di istanziare std :: vector

risposta

1

In the interview with Alexander Stepanov accenna al fatto che durante la proposta di aggiungere STL alla libreria Standard è stato chiesto di creare un'astrazione dal modello di memoria. Quindi, gli allocatori sono nati. Nel numero LWG issue c'è un esempio di implementazione in cui reference di allocatore personalizzato è definito come T __far&.

Ma, per ragioni sconosciute, perché non ho molto tempo per cercare, lo standard C++ 03 ha il seguente testo in §20.1.5 p4:

implementazioni di contenitori descritti in questo Gli standard internazionali sono autorizzati ad assumere che il loro parametro Modello di allocazione soddisfi i seguenti due requisiti aggiuntivi oltre a quelli della Tabella 32.

- Tutte le istanze di un determinato tipo di allocatore devono essere intercambiabili e confrontare sempre uguale a a vicenda.

- Il puntatore dei membri typedef, const_pointer, size_type e difference_type sono richiesti per essere T *, T const *, size_t e ptrdiff_t, rispettivamente.

Questo efficacemente elimina la capacità di allocatore di modelli di memoria personalizzati di interoperare con contenitori standard.

Durante la mia ricerca di tutti i documenti pre-C++ 11 che menzionano la parola "allocatore" ho trovato un notevole consenso per rimuovere quelle parole dallo standard. Infine, this paper propone di rimuoverli con il seguente commento:

Le parole di donnola sono sparite. Alza il tuo bicchiere e fai un brindisi.

Vittoria? Possiamo finalmente scatenarci con i nostri modelli di memoria? Non così tanto. Tra le altre cose, lo stesso articolo propone di rimuovere reference dai requisiti di allocatore. E sembra che sia stato votato nello standard.

Il LWG issue ho detto prima si oppone il cambiamento ma era chiuso con la seguente dichiarazione:

Nessun consenso a fare un cambiamento

Quindi sembra che lo scopo originario di ripartitori non è così importante oggi. Ecco cosa Wikipedia ha da dire:

Lo scopo attuale allocatori è dare il controllo del programmatore sopra allocazione di memoria all'interno di contenitori, piuttosto che adattare il modello di indirizzo dell'hardware sottostante. In effetti, lo standard modificato eliminava la capacità degli allocatori di rappresentare estensioni al modello di indirizzo C++, eliminando formalmente (e deliberatamente) il loro scopo originale.

Infine, lo Container::reference non ha nulla a che fare con gli allocatori. È stato creato per consentire le raccolte con proxy which are not actually containers. Quindi è qui per restare. A proposito, sembra che sia un altro esempio di come le parole finali dello Standard vadano contro le intenzioni originali.

+1

"per motivi sconosciuti" ma elencati nel secondo paragrafo della pagina di Wikipedia ... –

4

Perché quel typedef annidato è superfluo. Scott Meyers' STL efficace, pagina 49:

La norma consente in modo esplicito gli esecutori libreria per scontato che di ogni allocatore puntatore typedef è sinonimo di T * e typedef di riferimento di ogni di allocatore è la stessa T &

+0

Il documento a cui ho fatto il collegamento propone effettivamente la rimozione di questo dallo standard. – Lyberta

+0

Ha il potenziale per essere un cambiamento di rottura, quindi probabilmente stanno calpestando lentamente, srotolando riferimenti dal vettore e simili. Tuttavia, sono favorevole a rimuovere qualsiasi ambiguità dallo standard. –

2

http://en.wikipedia.org/wiki/Allocator_(C%2B%2B)

"Sono stati originariamente inteso come un mezzo per rendere la biblioteca più flessibile e indipendente dal modello di memoria di base, che permette ai programmatori di utilizzare i tipi di puntatore su misura e di riferimento con la libreria. Tuttavia, nel il processo di adozione di STL nello standard C++, il comitato di standardizzazione del C++ ha capito che un'astrazione completa del modello di memoria comportava penalità di performance inaccettabili.Per porvi rimedio, i requisiti degli allocatori sono stati resi più restrittivi. dagli allocatori è più limitato di quanto originariamente previsto da Stepanov."

Originariamente sono stati progettati per astrarre memoria stessa, che permette di allocare memoria per esempio, un'altra macchina via e connessione internet, e copiare i dati avanti e indietro utilizzando puntatori/riferimenti per tenere traccia di ciò che è vivo Allo stesso modo, si potrebbe creare un GC simile a Java in puro C++ Questa astrazione mi è sembrata un'idea incredibile!

Tuttavia, questo ha comportato sanzioni prestazionali ritenute inaccettabili al momento. Inoltre, se ci pensate, è quasi impossibile lavorare in codice. Ogni void func(const string&) dovrebbe essere trasformato in un template<class allocator> void func(allocator::reference), che è un contesto non deducibile in modo da Devo scrivere esplicitamente l'allocatore nella chiamata di funzione (func<std::allocator<std::string>::const_reference>(username)), cosa che nessuno farebbe, il che renderebbe il GC non funzionare correttamente. Oggigiorno, gli allocatori si limitano ad astrarre allocazione/deallocazione della memoria.

Problemi correlati