2010-07-13 11 views
10

einige Datenstruktur Angenommen:Referenz als Schlüssel in std :: map

typedef struct { 
    std::string s; 
    int i; 
} data; 

Wenn ich das Feld data.s als Schlüssel verwenden, wenn Instanzen von data in einer Karte des Typs std::map<std::string&, data> das Hinzufügen, tut die Zeichenkette kopiert wird? Ist es sicher, ein Element der Karte zu löschen, weil die Referenz ungültig wird?

Auch die Antworten auf diese Fragen gelten auch für eine unordered_map?

EDIT:

Dies ist meine aktuelle Lösung ... aber auf der Karte Iterator Zugabe ist UGLY:

typedef struct { 
    const std::string* s; 
    int i; 
} data; 

std::map<std::string, data> map; 
typedef std::map<std::string, data>::iterator iterator; 

// add an element to the map 
iterator add_element(const std::string& s) { 
    std::pair<iterator, bool> p = states.insert(std::make_pair(s, data())); 
    iterator i = p.first; 
    if(p.second) { 
     data& d = (*i).second; 
     d.s = &(*i).first; 
    } 
    return i; 
} 

Antwort

10

Sie keine Referenzen in Standard Library Container speichern kann - Ihre Karte sollte aussehen wie:

Die Karte wird sowohl die Schlüsselzeichenfolge und die Struct-Instanzen, die Kopien sein werden, für Sie verwalten. Sowohl map als auch unordered_map funktionieren in dieser Hinsicht genauso wie alle anderen Standard-Library-Container.

Beachten Sie, dass in C++, die Sie nicht brauchen typedefs structs zu erklären:

struct data { 
    std::string s; 
    int i; 
}; 
+0

Danke für die Antwort. Wenn ich zwei Kopien der Zeichenkette vermeiden möchte, sollte ich stattdessen lieber eine Referenz in den 'struct data' verwenden? –

+1

Wenn Sie sagen, dass ich keine Referenzen speichern kann, meinen Sie, dass die STL eine Kopie erzwingt? –

+2

@Helltone Referenzen sind als Mitglieder von Strukturen oder Klassen schwer zu verwenden - das ist nicht wirklich das, wofür sie bestimmt sind. Stattdessen sollten Sie einen Zeiger verwenden oder die Zeichenfolge aus der Struktur ganz weglassen. –

15

Sie können einen Blick auf boost.ref nehmen wollen. Es stellt ein Wrapper, die Verweise verwendet werden soll in STL-Container wie dies ermöglicht:

std::map<boost::reference_wrapper<std::string>, data> 

Ab C++ 11, ist dieser Teil des Standards ist (vor, dass Compiler, die TR1 implementieren auch bieten sie in der std::tr1 Namensraum).

0

Sie können die Referenz nicht verwenden. Die Karte kann den Inhalt kopieren. Dies ist vermutlich abhängig von der Implementierung.

Aber mit der Microsoft STL getestet.

struct data 
{ 
      data(data const& rhs) 
      { 
       a new object will be created here 
      } 
      std::string s; 
      int i; 
}; 

Fügen Sie einige Objekte zur Map hinzu und Sie werden in den Copy-Konstruktor gelangen. Dies sollte Ihre Referenz ungültig machen.

0

Ich glaube nicht, dass es einen großen Leistungszuwachs gibt, wenn Sie Zeiger anstelle von Objekt wählen. Tun Sie dies nur, wenn Sie Daten mit vielen vorhandenen String-Objekten verwalten, die im Container enthalten sein müssen. Auch die Zerstörung der Objekte muss vor dem Zerstören des Containers manuell gehandhabt werden.

Verwandte Themen