Domanda

Perché è che il singolo parametro del costruttore di std::list<T> richiede T essere un tipo default-costruibile? Voglio dire il seguente codice non viene compilato.

struct Foo { // does not have default constructor.
  Foo (int i) {} 
}
int main(void) {
  std::list<Foo> l(10);
}

Sembra possibile utilizzare il costruire e distruggere idiomi come hanno già fatto in std :: vector, anche se con maggiore contabilità della classe lista.

In una nota correlata, perché non hanno la funzione di capacità in lista? Si può sostenere che tale funzione sarebbe pagare il costo di allocazione di memoria up-front ed eliminare il sovraccarico in seguito come si push_back oggetti. Almeno farà le interfacce di due contenitori di sequenza STL leggermente più coerente.

È stato utile?

Soluzione

std :: elenco non ha una funzione di capacità, perché non ha senso; non deve mai ridimensionare come un vettore fa. La sua capacità è limitata solo dalla memoria disponibile, che non è facilmente determinata.

Da quello che hai chiesto, penso che in realtà si vuole di riserva (). Questo è un one-off per il vettore, perché (male) ha bisogno di una cosa del genere; non c'è alcuna particolare esigenza di fare tutte le funzioni coerenti in tutti i contenitori STL, soprattutto quando fanno poco senso per gli altri.

È possibile ottenere lo stesso effetto con un allocatore personalizzato. Come suggerito Manuel, guarda spinta.

Altri suggerimenti

Non c'è obbligo generale che il tipo sia costruibile di default - deve essere copiabile e assegnabili. Il tuo codice non funziona perché si tenta di creare una lista di 10 elementi - devono essere costruiti in qualche modo e in modo che il costruttore di default deve essere utilizzato - ma solo in questo caso specifico. Se è stata creata una lista vuota ed aggiunto ad essa, non ci sarebbe tale requisito.

Lo stesso vale per altri contenitori - provare a compilare il seguente:

#include <vector>

struct A {
    A( int x ) : z(x) {}
    int z;
};

std::vector <A> a(10);

Per quanto riguarda la seconda parte della tua domanda, mi basta osservare che la coerenza di interfaccia non è stato un criterio di progetto principale per i contenitori standard - non v'è alcuna intenzione, per esempio, che un tipo di contenitore è un "drop-in "la sostituzione per un altro. C'è una buona discussione di questo ai punti 1 e 2 del libro di Scott Meyers' 'STL efficace'.

Neil già risposto alla domanda principale .

Si noti inoltre che è necessario un costruttore di default quando si chiama ridimensionare ().

È possibile aggirare questo avendo un elenco STL di puntatori a oggetti, ma credo che questo era già evidente a voi.

  

In una nota correlata, perché non hanno la   la funzione di capacità in lista? Puoi   sostengono che tale funzione sarebbe disposto a pagare   costo allocazione di memoria up-front e   eliminare la testa in seguito, come si   oggetti push_back. Almeno lo farà   rendere le interfacce di due STL   container sequenziali leggermente più   coerente.

Credo che il problema qui è che liste STL consentono tra elenchi splicing . Se si desidera allocare la memoria in anticipo, hanno uno sguardo al Boost Pool Allocator .

La ragione è che, quando si costruisce una lista di n elementi (dove n è il parametro utilizzato nel costruttore), l'elenco riempie la sua struttura di n elementi con copie di T ().

SGI documentazione STL per la lista .

  

Perché è che l'unico parametro   costruttore di std :: list richiede T   per essere un tipo predefinito-costruibile?

Poiché questo contructor - Crea una lista di elementi (numero che si passa come parametro). Valore di ogni elemento sarà di default. Inoltre è possibile utilizzare costruttore con due parametri, per creare l'elenco di elementi che sarà inizializzato con il valore secondo elemento.

  

In una nota correlata, perché non hanno la   la funzione di capacità in lista?

Non ha senso, perché il costo di aggiungere nuovi elementi alla lista è molto più piccolo rispetto a caso con il vettore.

  

std :: vector non ha un tale   restrizione. La mia domanda è perché non   utilizzare le stesse tecniche   (Creare / distruggere idiomi) nel   std :: lista pure?

Non è restrizione. Perché se non si utilizza come costruttore, inizializzazione di default non sarà necessaria. Stessa cosa vale per vettore.

Quindi la tua domanda è in realtà "perché non hanno funzioni di riserva e di capacità in lista?"

La risposta è che non c'è alcun motivo per riservare la memoria in anticipo per la lista - l'aggiunta di nuovi elementi non richiede mai una realloc & copia per elementi esistenti, non c'è alcun obbligo che la memoria tenendo il contenuto di una lista di essere contigua, e iteratori non si ottiene invalidato quando si fa un list::push_back().

Tutte queste sono la ragione per l'esistenza di vector<>::reserve(), e avendo la memoria di riserva per i nuovi elementi è il motivo per cui un vector<> eseguirà il posizionamento new nella memoria crudo.

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