2009-09-04 6 views
24

Ich möchte eine Karte von Vektoren haben, (aber ich möchte nicht Zeiger für den internen Vektor verwenden), ist es möglich?Karte der Vektoren in STL?

// define my map of vector 
map<int, vector<MyClass> > map; 

// insert an empty vector for key 10. # Compile Error 
map.insert(pair<int, vector<MyClass> >(10, vector<MyClass>)); 

Ich weiß, dass, wenn ich Zeiger für Vektor verwendet haben, wie folgt, wäre es in Ordnung sein, aber ich frage mich, ob ich Zeiger und verwenden Sie die oben Datenstruktur vermeiden kann (ich will nicht manuell löschen)

// define my map of vector 
map<int, vector<MyClass>* > map; 

// insert an empty vector for key 10. 
map.insert(pair<int, vector<MyClass>* >(10, new vector<MyClass>)); 

Antwort

29

Die erste Datenstruktur wird funktionieren. Sie könnten zu typedef einen Teil des Codes soll künftig die Arbeit erleichtern:

typedef std::vector<MyClass>  MyClassSet; 
typedef std::map<int, MyClassSet> MyClassSetMap; 

MyClassSetMap map; 
map.insert(MyClassSetMap::value_type(10, MyClassSet())); 

oder (dank quamrana):

map[10] = MyClassSet(); 
15

Ja, aber Ihre zweite Zeile sein sollte:

map.insert(pair<int, vector<MyClass> >(10, vector<MyClass>())); 

Dies fügt ein Paar ein, das aus der Ganzzahl 10 und einem leeren Vektor besteht. Beide werden kopiert, und wenn Sie mit großen Vektoren arbeiten, sollten Sie vorsichtig mit Kopien sein.

Auch: Variablen nicht aufrufen "Karte" während using namespace std. Du machst mir Angst ;-)

+4

Es ist noch einfacher zu schreiben 'map.insert (std :: make_pair (10, Vektor ()));' – xtofl

+3

danke! Diese Website ist wirklich großartig! – chen

+0

@xtofl: Ja, ich meinte "sollte" im Sinne von "um den Compiler-Fehler loszuwerden". fbrereton macht auch gute Punkte, um den Code prägnanter zu machen. –

2

Sie fehlen nur ein Paar Klammern:

map.insert(pair<int, vector<MyClass> >(10, vector<MyClass>())); 

Übrigens gibt es eine Hilfsfunktion std :: make_pair die Pflege Argumente herzuleiten die Vorlage nimmt:

map.insert(make_pair(10, vector<MyClass>())); 

Die Verwendung eines Zeigers für einen dynamisch zugewiesenen Vektor ist eine eher schlechte Idee, da Sie dadurch für die Verwaltung der Instanz verantwortlich sind. Da die Karte ihre Inhalte niemals im Speicher bewegen sollte, gibt es auch keine leistungssteigernden Vorteile.

6

Mit dem typedefs von fbrereton Sie dies auch tun können:

typedef std::vector<MyClass>  MyClassSet; 
typedef std::map<int, MyClassSet> MyClassSetMap; 

MyClassSetMap map; 
map[10]=MyClassSet(); 

können Sie operator[] anstelle von insert(). Dies spart den Lärm Linie ein wenig.

+1

Ich glaube du meintest map [10] = MyClassSet(); Eigentlich sollte es auch möglich sein, nur map [10] zu schreiben; (um ein kleines Element der Überraschung hinzuzufügen). – UncleBens

+0

@UncleBens - Ups, yup, ich werde es reparieren! – quamrana

+0

Das hängt davon ab, wie das heißt. Einfügen kann schneller sein, wenn Sie wissen, dass es keine Konflikte geben wird. –

4

Sie sollten kompilieren Fehlermeldungen lesen. In der Regel erhalten Sie alle Informationen, die Sie benötigen.
Ihr Code gibt den Fehler 'illegal use of this type as an expression' in dieser Zeichenfolge aus. Das bedeutet, dass Sie Typ und kein Objekt verwenden. Um ein Objekt zu verwenden, könnten Sie einfach add() zum Aufruf des Konstruktors ohne Argumente hinzufügen.

map.insert(pair<int, vector<MyClass> >(10, vector<MyClass>())); 

Übrigens könnten Sie std :: make_pair verwenden, um Paare zu erstellen. Es leitet Argumenttypen ab, so dass sie nicht explizit angegeben werden müssen.

map.insert(make_pair(10, vector<MyClass>())); 
+0

+1 für Vorschlag zum Lesen von Compiler-Fehlern. Sie sind jedoch compilerspezifisch. Bei GCC ist der Fehler "primary-expression before ..." erwartet, was IMO eine allgemeine Bedeutung von "etwas ist hier falsch" hat - Sie müssen nur einen guten Blick auf den Code werfen, um es herauszufinden. (Der Versuch, mit verschiedenen Compilern zu kompilieren, könnte eine gute Idee sein, ich hatte Fehlermeldungen, die nicht nur unklar, sondern auch irreführend sind, zB "zweiter Parameter ist falsch", wo der Fehler im ersten Parameter lag.) – UncleBens

3

Sie könnten die Operatoren [] verwenden.
Diese werden den Wert in die Karte einfügen.

map[10]; // create the 10 element if it does not exist 
     // using the default constructor. 

Wenn Sie vorhaben, bald dann nach dem Bau verwenden:

std::vector<MyClass>& v = map[10]; 

Nun ist es aufgebaut und Sie haben eine lokale Referenz auf das Objekt.

5

Verwenden Sie die Swap-Funktion, um Ihren Vektor effizient hinzuzufügen.

map<int, vector<SomeClass> > Map; 

vector<SomeClass> vec; 
//...add elements to vec 

Map[1] = vector<int>(); 
// swap the empty vector just inserted with your vector. 
Map[1].swap(vec); 
2

Lässt ein wenig c 11 ++ verwenden;)

typedef std::vector<MyClass>  MyClassSet; 
typedef std::map<int, MyClassSet> MyClassSetMap; 

MyClassSetMap map; 
map.emplace(myid, MyClassSet()); 

Um zu wissen, ob diese eingefügt wurde Sie tun können:

const auto result = map.emplace(myid, MyClassSet()); 
return (result.second) 
? "Is_OK" 
: "Maybe "+myid+" exists\n"; 

Und hier ist das Flaggschiff von C++ 11 und Karten .... wie man in dieser Karte ein Paar einfügt, wenn es nicht existiert und wenn es existiert, füge einfach ein neues Element in den Vektor ein ....

const auto result = map.emplace(myid, MyClassSet()); 
result.first->second.emplace(objSet); 

Ich hoffe, geben Sie eine nützliche Information !!!

+1

Die map-Klasse stellt keine "emplace_back" -Funktion zur Verfügung (sie gehört relativ zu Vektor- und anderen Containern). Karte in anderen Händen bietet "emplace" und "emplace_hint" Funktionen – atari83

+0

Ja, völlig zustimmen. Ediited, Danke! – GutiMac

Verwandte Themen