ordne <int, int> Standardwerte zu

76
std::map<int,int> mapy;
++mapy[5];

Ist es sicher anzunehmen, dass dies mapy[5]immer 1 sein wird? Ich meine, wird mapy[5]immer der Standardwert 0 vor '++' erhalten, auch wenn nicht explizit deklariert, wie in meinem Code?

Bill Kotsias
quelle
2
Mögliches Duplikat des Standardwerts
eingebauten
3
@bobobobo: Diese Frage ist älter als der Standardwert von std :: map für den integrierten Typ . Der doppelte Wert sollte der Standardwert von std :: map für den integrierten Typ sein .
Promonet

Antworten:

122

Sobald Sie mit dem Operator [] auf die Karte zugreifen, wird der Schlüssel hinzugefügt, wenn er nicht vorhanden ist. Der Standardinitialisierer vom Typ int wird aufgerufen, sodass er den Wert 0 erhält.

rep_movsd
quelle
Soweit ich erfahren habe, ist der intAnfangswert eines nicht initialisierten Grundelements undefiniert - das heißt, er kann 0 oder -99765521 sein. Hatten Sie jemals eine intals Klassenvariable nicht initialisierte Variable und war einer dieser verrückten Werte in Ihrem Programm enthalten? Das heißt, ich habe das getestet und es scheint zu funktionieren. #include <stdio.h> #include <map> using namespace std; int main() { map<int,int> m ; for( int i = 0 ; i < 100 ; i++ ) m[i]++ ; for( const pair<int,int>& p : m ) printf( "m[%d] => %d\n", p.first, p.second ) ; }
Bobobobo
29
Es funktioniert anders als Sie denken. int x; lässt x einen undefinierten Wert erhalten int x = int (); Wieder bekommt x 0 Klasse foo {int x; foo (): x () {}}; foo f; Hier wird fx Null sein
rep_movsd
@ Bobobobo: Siehe meine Antwort. Die Initialisierung ist komplexer und hat je nach Kontext mehrere "Betriebsarten".
Leichtigkeitsrennen im Orbit
Ich dachte, die Werte in allen Containern werden im Heap erstellt, und der Wert im Heap wird mit einem geeigneten Wert initialisiert. In diesem Fall 0. Ist das richtig?
r0ng
1
In C ++ sind Heap- und Stack-Speicher nicht initialisiert - ein Objekt wird von seinem Standardkonstruktor initialisiert - die Sprache verfügt über Standardkonstruktoren für primitive Typen, die sie auf 0 initialisieren, wenn Sie es richtig aufrufen. Siehe meinen früheren Kommentar
rep_movsd
40

Ja, das ist sicher anzunehmen.

Die Karte wird wie operator[]folgt angegeben: ([map.access])

Effekte: Wenn es keinen Schlüssel gibt, xder der Karte entspricht, wird er in die Karte eingefügt value_type(std::move(x), T()).
Rückgabe: Ein Verweis auf das mapped_typeentsprechende xin *this.

T()verwendet Wert-Initialisierung für alle Taußer void ([expr.type.conv] / 2) , und die Mehrwert-Initialisierung für ein primitives Ergebnis in Null-Initialisierung ([dcl.init] / 7) .

Daher ergibt der Ausdruck eine Referenz auf ein Objekt mit dem Wert Null ([dcl.init] / 5) .

Der operator++Aufruf erhöht dann dieses Objekt auf eins und wertet es auf eins aus.

(Alle Referenzen sind C ++ 11.)

Leichtigkeitsrennen im Orbit
quelle
2
Keine Ahnung, warum Ihre Antwort abgelehnt wurde, weil Sie richtig sind. Genau das steht in der Spezifikation (habe es einfach selbst überprüft).
Hans de Ruiter
9

Ja, der Standardwert ist der Standardwert dieses Typs. Wenn Sie einen anderen Standardwert wünschen, können Sie eine Klasse erstellen, die sich wie ein int verhält, aber einen anderen Standardkonstruktor hat.

Rasmus Kaj
quelle
6

Die Antwort von Rep_Movsd ist zu stark vereinfacht und führt wahrscheinlich zu zahlreichen äußerst gefährlichen Missverständnissen. Primitive Datentypen in C ++ haben keine Initialisierer. Louis Brandy hatte einen wunderbaren Vortrag, in dem er viele häufige C ++ - Fehler bei Facebook diskutierte. Ein Missverständnis darüber, wie std :: map <> [] funktioniert, war einer der Fehler, die er diskutierte. Dies ist eine ausgezeichnete Ressource, obwohl er dies nicht tut Gehen Sie ins Detail, wie std :: map <> [] tatsächlich funktioniert.

Im Allgemeinen werden Ints nicht initialisiert und sind wie alle primitiven Typen undefiniert. Bei Verwendung mit std :: map <> [] hat der int einen Standardwert von Null, der durch einen Prozess namens Wertinitialisierung festgelegt wird. Die Wertinitialisierung ist ein Prozess, der im Allgemeinen mit Strukturen funktioniert. Zum Beispiel,

struct Struct {
Struct() : memberVariable() {}
       int memberVariable;
};

Initialisiert das int immer auf Null. Wenn die Elementvariablen andere primitive Typen wären, hätten sie auch spezifische Initialisierungswerte. Zum Beispiel werden die folgenden Typen durch Wertinitialisierung wie folgt initialisiert:

bool = false
float = 0.0f
enum = (Aufzählungstyp) 0
Zeiger = Nullzeiger
Zeiger auf Mitglied = Null Elementzeiger

Seien Sie äußerst vorsichtig, wenn Sie mit Daten arbeiten, die nicht explizit initialisiert wurden. Eine letzte Sache, betrachten Sie den folgenden Code

map<string, int> myMap;
cout << myMap["Foo"];

Dieser Code initialisiert nicht nur immer die Ganzzahl auf 0, sondern fügt auch 0 in die Karte ein. Um es kurz zusammenzufassen: Primitive Datentypen sind undefiniert, wenn sie nicht initialisiert werden. In einigen Fällen, z. B. bei einer Struktur- oder Kartenwertinitialisierung, werden die primitiven Daten jedoch mit einem bestimmten Wert initialisiert.

Rachel Casey
quelle
2
"Primitive Datentypen in C ++ haben keine Initialisierer" Dies ist zu stark vereinfacht und führt wahrscheinlich zu gefährlichen Missverständnissen. "nicht initialisiert" Nein. Nun, nicht ganz. Es heißt Standardinitialisierung, aber ja, das Ergebnis ist ein unbestimmter Wert (C ++ 11 8.5 / 11). "sind undefiniert" Nein. Unbestimmt. "structs" C ++ hat keine Strukturen. "Wertinitialisierung" Richtig. Der entscheidende Punkt ist die unterschiedliche Art der Initialisierung. Sie haben auch einige Kommaspleiße in Ihrer Prosa.
Leichtigkeitsrennen im Orbit
Primitive Datentypen werden standardmäßig nicht mit einem Wert initialisiert. Sie haben keine Standardkonstruktion. In einigen Fällen haben sie eine Wertkonstruktion. Die Unterscheidung, die Sie zwischen einem undefinierten und einem unbestimmten Verhalten treffen möchten, ist absurd. Gemäß dem C ++ 11-Standard ist undefiniertes Verhalten definiert als: "... nicht portierbares oder fehlerhaftes Programmkonstrukt oder fehlerhafte Daten, für die dieser Internationale Standard keine Anforderungen stellt", was im Wesentlichen bedeutet, dass ein Fehler in der Logik oder im Status aufgetreten ist und das Ergebnis ist unbekannt. Ich habe nie gesagt, dass Strukturen aus C ++ stammen.
Rachel Casey
"Die Unterscheidung, die Sie zwischen einem undefinierten und einem unbestimmten Verhalten treffen wollen, ist absurd." Ich habe nicht unterschieden, der Standard schon. Wenn Sie das für absurd halten, können Sie natürlich Einwände gegen die Mailingliste der ISO-Arbeitsgruppe erheben.
Leichtigkeitsrennen im Orbit
"Ich habe nie gesagt, dass Strukturen aus C ++ stammen." Wenn Sie dies bereits wissen, warum haben Sie dann in einer C ++ - Frage über Strukturen gesprochen? Nun , das ist absurd!
Leichtigkeitsrennen im Orbit
1
Nein. Es ist nicht möglich, eine Struktur in C ++ zu erstellen. Es ist nur möglich, eine Klasse mit dem geerbten structSchlüsselwort zu erstellen . Der von Ihnen angezeigte Code enthält eine Klasse . C ++ hat keine Strukturen. Weiterführende Literatur: stackoverflow.com/a/36917400/560648 stackoverflow.com/a/34108140/560648
Leichtigkeitsrennen im Orbit