2009-09-04 11 views
24

Voglio avere una mappa di vettori, (ma non voglio usare il puntatore per il vettore interno), è possibile?mappa dei vettori 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>)); 

so che se ho usato puntatore per il vettore, come segue, sarebbe bene, ma mi chiedo se posso evitare di utilizzare il puntatore e utilizzare la struttura dei dati di cui sopra (Non voglio eliminare manualmente)

// 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>)); 

risposta

29

La prima struttura dati funzionerà. Si potrebbe desiderare di typedef parte del codice per rendere il futuro lavoro più facile:

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

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

o (grazie quamrana):

map[10] = MyClassSet(); 
15

Sì, ma la seconda linea dovrebbe essere:

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

Inserisce una coppia composta dal numero intero 10 e un vettore vuoto. Entrambi saranno copiati e, se hai a che fare con vettori di grandi dimensioni, dovrai fare attenzione alle copie.

Inoltre: non chiamare le variabili "map" mentre using namespace std. Mi stai spaventando ;-)

+4

È ancora più facile scrivere 'map.insert (std :: make_pair (10, vector ()))' – xtofl

+3

grazie! questo sito è davvero fantastico! – chen

+0

@xtofl: sì, intendevo "dovrebbe" nel senso di "sbarazzarsi dell'errore del compilatore". fbrereton ha anche dei buoni punti per rendere il codice più conciso. –

2

Stai solo manca un paio di parentesi:

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

Per inciso, c'è uno std :: make_pair funzione di supporto che si prende cura di dedurre gli argomenti di modello:

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

Considerare l'utilizzo di un puntatore al vettore assegnato dinamicamente è invece un'idea piuttosto negativa, poiché ciò renderà responsabile la gestione dell'istanza. Inoltre, dal momento che la mappa non dovrebbe mai spostare il suo contenuto in memoria, non c'è nulla da guadagnare neanche in termini di prestazioni.

6

Utilizzando le typedef da fbrereton si può anche fare questo:

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

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

È possibile utilizzare operator[] invece di insert(). Ciò consente di risparmiare sul rumore di linea un po '.

+1

Penso che intendessi map [10] = MyClassSet(); In realtà dovrebbe anche essere possibile scrivere solo la mappa [10]; (aggiungere un piccolo elemento di sorpresa). – UncleBens

+0

@UncleBens - Oops, sì, lo aggiusterò! – quamrana

+0

Questo dipende da come viene chiamato. Inserisci potrebbe essere più veloce se sai che non ci saranno conflitti. –

4

Si consiglia di leggere i messaggi di errore di compilazione. Di solito ti danno tutte le informazioni di cui hai bisogno.
Il codice restituisce l'errore 'illegal use of this type as an expression' in tale stringa. Ciò significa che usi il tipo, non un oggetto. Per usare un oggetto si può semplicemente aggiungere() per chiamare il costruttore senza argomenti.

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

A proposito, è possibile utilizzare std :: make_pair per creare coppie. Deduce i tipi di argomenti, quindi non è necessario indicarli esplicitamente.

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

+1 per il suggerimento di leggere gli errori del compilatore. Tuttavia, sono specifici del compilatore. Con GCC l'errore è "espressione primaria attesa prima ...", che IMO ha un significato generico di "qualcosa non va qui" - basta dare un'occhiata al codice per capirlo. (Cercando di compilare con compilatori diversi potrebbe essere una buona idea, ho avuto messaggi di errore non solo non chiari ma fuorvianti, ad esempio "secondo parametro sbagliato" in cui l'errore era nel primo parametro.) – UncleBens

3

È possibile utilizzare gli operatori [].
Questi inseriranno il valore nella mappa.

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

Se avete intenzione di utilizzare subito dopo la costruzione poi:

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

Ora il suo costruiti e si ha un riferimento locale all'oggetto.

5

Utilizzare la funzione di scambio per aggiungere il vettore in modo efficiente.

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

Consente di utilizzare un po 'C++ 11;)

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

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

sapere se questo è stato inserito si può fare:

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

E qui è il fiore all'occhiello di C++ 11 e mappe .... come inserire in questa mappa una coppia se non esiste e se esiste basta inserire un nuovo elemento nel vettore ....

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

Spero di dare un'informazione utile !!!

+1

Se la mia memoria serve, la classe map non fornisce la funzione "emplace_back" (appartiene relativamente al vettore e ad altri contenitori). mappa in altre mani fornisce funzioni "emplace" e "emplace_hint" – atari83

+0

Sì, completamente d'accordo. Ediited, grazie! – GutiMac

Problemi correlati