Was ist der Unterschied zwischen const und non const key?


Antworten:


65
  • intund const intsind 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 constist 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 constFolgendes 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 constfunktioniert der Versuch, einen Schlüssel zu verwenden, einfach nicht.


1
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 .
Mitchnull

@mitchnull Ja, guter Ort. ( Übrigens !)
Leichtigkeitsrennen im Orbit

@LightnessRacesinOrbit "Der Standard verlangt offiziell, dass Ihr Schlüsseltyp kopierbar und beweglich ist". In Bezug auf die Beweglichkeit kann ich nicht feststellen, dass Sie auf der C ++ - Standardkopie, die ich habe, bitte eine Referenz- oder Abschnittsnummer angeben können.
Beren

Dies ist eine ausgezeichnete Antwort, die schließlich das constProblem 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 :)
vsoftco

Ah, danke, dass Sie bestätigt haben, dass Schlüssel nicht const sein dürfen. Ich wollte, dass meine Schlüssel unveränderlich sind und es hat mich verrückt gemacht -_-
Noel Widmer

36

Der Schlüssel ist bereits vorhanden const, daher ist das Schreiben constin diesem Fall überflüssig . Sobald ein Element eingegeben wurde, keykann es nicht mehr geändert werden.


Bearbeiten :

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 constsowieso ein ...

Also abschließend. Der einzige Unterschied ist, dass es sich um zwei verschiedene Typen handelt. Sie sollten sich um nichts anderes kümmern.


18
Dies ist nicht (vollständig) korrekt. Die Schnittstelle von std::mapmacht 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 .
Jrok

1
@jrok ist korrekt, diese Antwort jedoch nicht. Das key_typeist in der Tat noch intim ersteren Fall.
Leichtigkeitsrennen im Orbit

6
@ johnmac2332: Lass dies eine Lektion sein, die so schnell ist! = perfekt und positiv! = richtig.
Leichtigkeitsrennen im Orbit

1
@ johnmac2332 Schnelle und schnelle Antworten sollten sehr geschätzt werden. Dies ist einer der hochwertigen Stackoverflow besser als andere Bahnen. OP kann im Kommentarbereich weiter abfragen. Wenn er Danke sagt, hat er wahrscheinlich die Antwort bekommen.
Grijesh Chauhan

2
Niemand ist perfekt, wir alle machen Fehler und lernen voneinander. Wir sind hier, um zu lernen und zu helfen :)
Maroun

8

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 Tgeschriebenen 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.



2

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.


"Abstürze" auf welche Weise?
Leichtigkeitsrennen im Orbit

@LightnessRacesinOrbit Es wurde über std::map::insertmehrere Deklarationen geklagt .
7.

Ja, wie oben erwähnt: Es macht einen Unterschied für den Compiler.
7.

Wenn wir "Absturz" sagen, beziehen wir uns normalerweise auf eine unerwartete und unansehnliche Laufzeitbeendigung eines Prozesses. Compiler-Abstürze sind selten, treten jedoch auf (insbesondere bei neuen Sprachfunktionen) und sind sehr schwerwiegend (je nach Erstellungsergebnissen).
Leichtigkeitsrennen im Orbit

Es stürzt mein Build ab , nicht die Anwendung . Missbrauche ich die Terminologie?
7.

0

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;
}

1
Wenn das key_typeist const int*, ist der Zeiger selbst nicht const, aber der spitze intist const.
Lrineau

-1

const bezieht sich auf eine Konstante, die, sobald sie definiert ist, nicht mehr geändert werden kann. und "Änderung" kann in nicht konstanten Sachen auftreten oder nicht.

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.