Frage

Warum ist, dass die einzelnen Parameter Konstruktor std::list<T> T erfordert eine Standard-konstruierbaren Typ sein? Ich meine, der folgende Code nicht kompiliert.

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

Es scheint möglich, die Idiome zu konstruieren und zu zerstören als sie haben bereits in dem std :: vector, wenn auch mit mehr buchhalte der Liste Klasse getan.

über einen entsprechenden Hinweis, warum nicht die Kapazität Funktion in der Liste hat? Sie können argumentieren, dass eine solche Funktion Speicher Verrechnungskostenart up-front zahlen würde und den Aufwand beseitigen später, wie Sie Objekte push_back. Zumindest wird es die Schnittstellen von zwei STL-Sequenz-Containern etwas konsistenter machen.

War es hilfreich?

Lösung

std :: Liste keine Kapazitätsfunktion hat, weil es keinen Sinn macht; es hat nie um die Größe wie ein Vektor der Fall ist. Es ist Kapazität nur durch den verfügbaren Speicher begrenzt ist, die sich nicht leicht bestimmt wird.

Von dem, was Sie gefragt, ich glaube, Sie tatsächlich Reserve wollen (). Das ist eine einmalige für Vektor, weil es (schlecht) braucht so etwas; es gibt keine besondere Anforderung alle Funktionen konsistent über alle STL-Container zu machen, vor allem, wenn sie wenig Sinn für die andere.

machen

Sie können den gleichen Effekt mit einem benutzerdefinierten allocator erreichen. Wie Manuel vorgeschlagen, schauen zu steigern.

Andere Tipps

Es gibt keine allgemeine Anforderung, dass der Typ Standard konstruierbar sein - es kopierbar und belegbar sein müssen. Der Code funktioniert nicht, weil Sie versuchen, eine Liste von 10 Stück zu schaffen - sie haben irgendwie konstruiert werden und so der Standardkonstruktor muss verwendet werden - aber nur in diesem speziellen Fall. Wenn Sie eine leere Liste erstellt und hinzugefügt, um es, gäbe es keine solche Anforderung sein.

Das gleiche gilt für andere Behälter - versuchen, die folgenden Zusammenstellung:

#include <vector>

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

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

In Bezug auf den zweiten Teil Ihrer Frage, würde ich beobachte nur, dass die Konsistenz der Schnittstelle wurde nicht ein gutes Designkriterium für die Standardcontainer - es ist nicht beabsichtigt, zum Beispiel, dass eine Art von Behälter ein „Drop-in ist "Ersatz für einen anderen. Es gibt eine gute Diskussion über diesen in Artikel 1 und 2 von Scott Meyers Buch "Effective STL".

Neil beantwortet bereits die Hauptfrage .

Beachten Sie auch, dass Sie einen Standard-Konstruktor benötigen, wenn die Größe () aufrufen.

Sie können dies umgehen, indem sie eine STL Liste von Zeigern auf Objekte, die aber ich denke, das ist schon klar war, zu dir.

  

über einen entsprechenden Hinweis, warum nicht die   Kapazität Funktion in der Liste? Du kannst   argumentieren, dass eine solche Funktion zahlen   Speicherzuordnung Kosten up-front und   beseitigt den Aufwand später, wie Sie   push_back Objekte. Zumindest wird es   machen die Schnittstellen von zwei STL   Sequenz Behälter etwas mehr   konsistent ist.

Ich denke, das Problem hier ist, dass STL-Listen ermöglichen Quer Liste Spleißen . Wenn Sie Speicher im Voraus zuweisen möchten, einen Blick auf die Boost-Pool Allocator .

Der Grund dafür ist, dass, wenn Sie eine Liste von n Elementen konstruieren (wobei n die Parameter, die Sie im Konstruktor verwendet wird), ist die Liste seiner Struktur von n Elementen mit Kopien von T füllt ().

Siehe sgi stl Dokumentation Liste .

  

Warum ist, dass die einzelnen Parameter   Konstruktor von std :: list erfordert T   einen default-konstruierbaren Typ sein?

Da diese contructor - erstellt Liste mit Elementen (Nummer, die Sie als Parameter übergeben). Wert jedes Elements wird Verzug. Auch Sie könnten Konstruktor mit zwei Parametern verwenden, um erstellen Liste mit Elementen, die mit dem zweiten Element Wert initialisiert wird.

  

über einen entsprechenden Hinweis, warum nicht die   Kapazität Funktion in der Liste?

Es hat keinen Sinn, weil Kosten neue Elemente zur Liste hinzuzufügen viel kleiner ist als in dem Fall mit dem Vektor.

  

std :: vector verfügt nicht über eine solche   Beschränkung. Meine Frage ist, warum nicht   verwenden die gleichen Techniken   (Create / destroy Idiome) in der   std :: list auch?

Es ist nicht Beschränkung. Denn wenn Sie keinen Konstruktor verwenden, Standardinitialisierung nicht erforderlich. Das Gleiche gilt gilt für Vektor.

So Ihre Frage ist wirklich, „warum nicht Reserve und Kapazitäts Funktionen in der Liste hat?“

Die Antwort darauf ist, dass es keinen Grund gibt, Speicher im Voraus für die Liste zu reservieren - das Hinzufügen neuer Elemente erfordert nie eine realloc & kopieren für bestehende Elemente, dann ist es nicht erforderlich, dass der Speicher den Inhalt einer Liste zusammenhängend sein zu halten, und Iteratoren nicht für ungültig erklärt werden, wenn ein list::push_back() tun.

Alle diese sind der Grund für die Existenz von vector<>::reserve() und für neue Elemente in Reserve Speicher ist, warum ein vector<> wird Platzierung new in rohe Speicher durchführen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top