Was passiert, wenn ich den Wert einer Karte lese, bei der der Schlüssel nicht vorhanden ist?


78
map<string, string> dada;
dada["dummy"] = "papy";
cout << dada["pootoo"];

Ich bin verwirrt, weil ich nicht weiß, ob es sich um undefiniertes Verhalten handelt oder nicht. Woher weiß ich, wenn ich einen Schlüssel anfordere, der nicht existiert? Benutze ich stattdessen einfach find?

Antworten:


84

Das map::operator[]durchsucht die Datenstruktur nach einem Wert, der dem angegebenen Schlüssel entspricht, und gibt einen Verweis darauf zurück.

Wenn es keines findet, erstellt es transparent ein standardmäßig erstelltes Element dafür. (Wenn Sie dieses Verhalten nicht möchten, können Sie map::atstattdessen die Funktion verwenden.)

Eine vollständige Liste der Methoden von std :: map finden Sie hier:

http://en.cppreference.com/w/cpp/container/map

Hier ist die Dokumentation des map::operator[]aktuellen C ++ - Standards ...

23.4.4.3 Zugriff auf Kartenelemente

T& operator[](const key_type& x);

  1. Effekte: Wenn die Karte keinen Schlüssel enthält, der x entspricht, wird value_type (x, T ()) in die Karte eingefügt.

  2. Erforderlich: key_type muss CopyConstructible sein und mapped_type muss DefaultConstructible sein.

  3. Rückgabe: Ein Verweis auf den mapped_type, der x in * this entspricht.

  4. Komplexität: logarithmisch.

T& operator[](key_type&& x);

  1. Effekte: Wenn in der Karte kein Schlüssel vorhanden ist, der x entspricht, wird value_type (std :: move (x), T ()) in die Karte eingefügt.

  2. Erforderlich: mapped_type muss DefaultConstructible sein.

  3. Rückgabe: Ein Verweis auf den mapped_type, der x in * this entspricht.

  4. Komplexität: logarithmisch.


Ich habe eigentlich nirgendwo im Standard gefunden, dass es das sagt. Zumindest nicht um 23.3.1.2 [lib.map.access] oder irgendwo anders, an das ich mich erinnern konnte, es zu überprüfen. EDIT: Anscheinend habe ich mir eine alte Version des Standards angesehen. Mein Fehler.
Vlad Ciobanu

@VladCiobanu: Oben ist 23.4.4.3 wörtlich kopiert. Verwenden Sie die aktuelle Version ISO/IEC 14882:2011(E)?
Andrew Tomazos

20

Wenn Sie versuchen , einen für den Zugriff key valuemit Index - Operator [], dann können zwei Dinge passieren:

  1. Die Karte enthält dies key. Es wird also das entsprechende zurückgegebenkey value .
  2. Die Karte enthält nicht die key. In diesem Fall wird keyder Karte automatisch ein mit hinzugefügt null value.

"pootoo"Schlüssel existiert nicht in Ihrer Karte. Also wird es automatisch keymit value = ""(leere Zeichenfolge) hinzugefügt . Und Ihr Programm druckt eine leere Zeichenfolge.

Hier wird die Kartengröße um erhöht 1.

Sie können einen Schlüssel suchen map_name.find(), der zurückgegeben wird, map_name.end()wenn der Schlüssel nicht vorhanden ist. Und es wird kein Extra keyhinzugefügt.

Sie können den []Operator verwenden, wenn Sie einen Wert für einen Schlüssel festlegen möchten.


7

Es ist kein undefiniertes Verhalten. Wenn operator []für den angegebenen Schlüssel kein Wert gefunden wird, wird an dieser Position einer eingefügt.


6

Wenn Sie für Operator [] versuchen, auf einen Wert für einen nicht vorhandenen Schlüssel zuzugreifen, wird ein neues Wertobjekt, das standardmäßig erstellt wurde, in die Karte eingefügt und seine Referenz zurückgegeben.


2

Das operator[]for mapgibt eine nicht konstante Referenz zurück und Sie können diese wie in Ihrer zweiten Zeile gezeigt zuweisen. Wenn Sie auf diese Weise zugreifen, wird ein standardmäßig erstelltes Element vom valueTyp erstellt.

Wenn Sie ein Element finden möchten, ist ein besserer Weg

iterator find ( const key_type& x )

(oder die const-Alternative), die einen Iterator zurückgibt, der gleich ist, <map>.end()wenn der Schlüssel nicht gefunden wird oder wenn Sie nur wissen möchten, ob er in der Sammlung enthalten ist, die Sie verwenden können

size_type count ( const key_type& x ) const

Dies gibt für eine Karte immer entweder 1 oder 0 zurück, da die Schlüssel eindeutig sind.


1

Wenn der Operator [] keinen Wert für den angegebenen Schlüssel findet, fügt er an dieser Position einen ein.

Aber Sie sollten beachten , dass , wenn Sie einen Besuch not exist keyund rufen Sie es der Member - Funktion, wie mapKV [not_exist_key] .member_fun (). Das Programm abstürzen.

Lassen Sie mich ein Beispiel geben, Testklasse wie folgt:

struct MapValue{
    int val;

    MapValue(int i=0){
        cout<<"ctor: "<<i<<endl; val = i;
    }

    ~MapValue(){
        cout<<"dtor: "<<val<<endl;
    }

    friend ostream& operator<<(std::ostream& out, const MapValue& mv){
        cout<<"MapValue: "<<mv.val<<endl;
    }

    string toString(){
        cout<<"MapValue: "<<val<<endl;
    }
};

Testcode:

cout<<"-------create map<int, MapValue>-------"<<endl;

map<int, MapValue> idName{{1, MapValue(1)}, {2, MapValue(2)}};

cout<<"-----cout key[2]-----"<<endl;
cout<<idName[2]<<endl;

cout<<"-----cout key[5]-----"<<endl;
cout<<idName[5]<<endl;

cout<<"------- runs here means, does't crash-------"<<endl;

Ausgabe wie folgt:

-------create map<int, MapValue>-------
ctor: 1
ctor: 2
dtor: 2
dtor: 1
dtor: 2
dtor: 1
-----cout key[2]-----
MapValue: 2

-----cout key[5]-----
ctor: 0
MapValue: 0

-------runs here means, does't crash-------
dtor: 0
dtor: 2
dtor: 1

Wir können das sehen: Rufen Sie idName[5]das Kartenkonstrukt {5, MapValue(0)}auf, um es in idName einzufügen.

Wenn Sie jedoch die Mitgliedsfunktion von aufrufen idName[5], stürzt das Programm ab:

cout<<"-------create map<int, MapValue>-------"<<endl;

map<int, MapValue> idName{{1, MapValue(1)}, {2, MapValue(2)}};


idName[5].toString();  // get crash here.


cout<<"------- runs here means, doesn't crash-------"<<endl;

es sollte nicht abstürzen, weil die Karte ein anderer Fehler sein muss
isti_spl

0

Bitte schauen Sie sich die Ausnahme out_of_range an: http://www.cplusplus.com/reference/stdexcept/out_of_range/

Dies wird von map :: at und map :: operator [] ausgelöst, wenn der Schlüssel nicht vorhanden ist. Sie können es genauso abfangen wie das Vektorbeispiel im Link.

Sie können auch Folgendes verwenden: http://www.cplusplus.com/reference/map/map/find/

Und gegen map :: end prüfen


4
nein, nur map :: at throw, map :: operator [] erstellt einen neuen value_type, wenn der Schlüssel nicht vorhanden ist
galka
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.