Was ist der Unterschied zwischen den folgenden beiden Zeilen?
map<int, float> map_data;
map<const int, float> map_data;
Was ist der Unterschied zwischen den folgenden beiden Zeilen?
map<int, float> map_data;
map<const int, float> map_data;
Antworten:
int
und const int
sind zwei verschiedene Typen.
std::map<int, float>
und std::map<const int, float>
sind in ähnlicher Weise verschiedene Typen.
Der Unterschied zwischen std::map<const int, float>
und std::map<int, float>
ist bis zu einem gewissen Grad analog zu dem Unterschied zwischen beispielsweise std::map<int, float>
und std::map<std::string, float>
; Sie erhalten jeweils einen neuen Kartentyp.
Im Nichtfall const
ist der interne Schlüsseltyp immer noch nicht const
int
:
std::map<const int, float>::key_type => const int
std::map<int, float>::key_type => int
Kartenschlüssel sind jedoch semantisch unveränderlich, und alle Kartenoperationen , die den direkten Zugriff auf Schlüssel ermöglichen (z. B. Dereferenzieren von Iteratoren, was ergibt value_type
), führen const
Folgendes aus key_type
:
std::map<const int, float>::value_type => std::pair<const int, float>
std::map<int, float>::value_type => std::pair<const int, float>
So ist der Unterschied kann in jeder Hinsicht Sie weitgehend unsichtbar sein , dass Angelegenheiten, wenn Ihre Implementierung zulässt.
Dies ist jedoch nicht immer der Fall: Der Standard verlangt offiziell, dass Ihr Schlüsseltyp kopierbar und verschiebbar ist, und einige Implementierungen verwenden Kartenknoten wieder . Unter diesen Implementierungen const
funktioniert der Versuch, einen Schlüssel zu verwenden, einfach nicht.
So the difference is largely invisible to you in every way that matters.
- es sei denn, Sie verwenden eine stdlib, die Schlüssel kopiert / verschiebt (wie libc ++). In diesem Fall bricht die const-Version nur. Eine entsprechende Diskussion finden Sie unter lists.cs.uiuc.edu/pipermail/cfe-dev/2011-July/015926.html .
const
Problem der Gesamtheit mit Karten verdeutlichte . C ++ 14 führte die transparenten Komparatoren ein, die ein wenig Komplexität hinzufügen, nur um uns scharf zu halten :)
Der Schlüssel ist bereits vorhanden const
, daher ist das Schreiben const
in diesem Fall überflüssig . Sobald ein Element eingegeben wurde, key
kann es nicht mehr geändert werden.
Wie in den Kommentaren erwähnt, gibt es einen Unterschied zwischen den beiden Zeilen. Wenn Sie beispielsweise eine Funktion schreiben, die akzeptiert map<const int, int>
, können Sie sie nicht übergeben, map<int, int>
da es sich um verschiedene Typen handelt .
Beachten Sie jedoch, dass sie sich, obwohl sie unterschiedliche Typen sind, gleich verhalten, da der Schlüssel in einer Karte const
sowieso ein ...
Also abschließend. Der einzige Unterschied ist, dass es sich um zwei verschiedene Typen handelt. Sie sollten sich um nichts anderes kümmern.
std::map
macht den Schlüsseltyp als verfügbar const
, aber das bedeutet nicht, dass die beiden Vorlageninstanziierungen identisch sind, wie diese Antwort möglicherweise impliziert. std::map<const int, float>
und std::map<int, float>
sind verschiedene Arten .
key_type
ist in der Tat noch int
im ersteren Fall.
Der Unterschied besteht darin, dass die zweite Variante den Schlüsseltyp für die Karte als festlegt const int
. Unter dem Gesichtspunkt der "Modifizierbarkeit" ist dies redundant, da die Karte ihre Schlüssel bereits als speichertconst
Objekte .
Dies kann jedoch auch zu unerwarteten und nicht offensichtlichen Unterschieden im Verhalten dieser beiden Karten führen. In C ++ unterscheidet sich eine für Typ geschriebene Vorlagenspezialisierung von einer für Typ T
geschriebenen Spezialisierung const T
. Das bedeutet, dass die beiden oben genannten Versionen der Karte möglicherweise unterschiedliche Spezialisierungen verschiedener "Satelliten" -Vorlagen verwenden, die vom Schlüsseltyp abhängen. Ein Beispiel ist das Schlüsselkomparator-Prädikat. Der erste wird verwendet, std::less<int>
während der zweite verwendet wirdstd::less<const int>
. Indem Sie diesen Unterschied ausnutzen, können Sie diese Karten einfach erstellen, um ihre Elemente in unterschiedlicher Reihenfolge zu sortieren.
Probleme wie diese sind bei den neuen C ++ 11-Containern wie z std::unordered_map
. std::unordered_map<const int, int>
wird nicht einmal kompiliert, da versucht wird, eine std::hash<const int>
Spezialisierung zum Hashing der Schlüssel zu verwenden. Eine solche Spezialisierung gibt es in der Standardbibliothek nicht.
const
kann nach dem Einstellen nicht mehr geändert werden. Und ja, laut Dokumentation und anderer Antwort sollten Sie sich daran erinnern, dass dies bereits der Fall key
ist const
.
Link: http://www.cplusplus.com/reference/map/map/ Link: http://en.cppreference.com/w/cpp/container/map
Während das Verhalten Ihrer Anwendung normalerweise das gleiche ist, macht es für einige Compiler, die Sie möglicherweise verwenden, einen Unterschied. Das spezifischere Beispiel dafür, was mich überhaupt auf diese Seite gebracht hat:
Explizite Angabe einer Karte als map<const key, value>
Builds erfolgreich mit dem gnu-Toolkit;
Ein Studio12 Solaris x86-Build stürzt jedoch ab.
map<key, value>
baut erfolgreich auf beiden auf. Das Verhalten der Anwendung bleibt unverändert.
std::map::insert
mehrere Deklarationen geklagt .
Const-Schlüssel können hilfreich sein, wenn die Schlüssel Zeiger sind. Wenn Sie const-Schlüssel verwenden, können Sie das spitze Objekt beim Zugriff auf die Schlüssel nicht ändern. Beachten Sie Folgendes:
#include <map>
#include <string>
int glob = 10;
int main() {
std::map<const int*, std::string> constKeyMap { { &glob, "foo"} };
std::map<int*, std::string> keyMap { { &glob, "bar" } };
for(const auto& kv : keyMap) { *(kv.first) = 20; }; // glob = 20
for(const auto& kv : constKeyMap) { *(kv.first) = 20; }; // COMPILE ERROR
return 0;
}
key_type
ist const int*
, ist der Zeiger selbst nicht const, aber der spitze int
ist const.