Verwendung von int
ist aus logischer Sicht für die Indizierung eines Arrays besser geeignet.
unsigned
semantisch in C und C++ nicht wirklich "nicht negativ" bedeutet, sondern eher wie "Bitmaske" oder "Modulo Integer" ist.
Um zu verstehen, warum unsigned
kein guter Typ für eine "nicht-negative" Zahl ist, beachten Sie bitte diese völlig absurden Aussagen:
- Addiert man eine möglicherweise negative ganze Zahl zu einer nichtnegativen ganzen Zahl, erhält man eine nichtnegative ganze Zahl
- Die Differenz zweier nichtnegativer ganzer Zahlen ist immer eine nichtnegative ganze Zahl
- Multipliziert man eine nichtnegative ganze Zahl mit einer negativen ganzen Zahl, erhält man ein nichtnegatives Ergebnis
Offensichtlich ergibt keiner der obigen Sätze irgendeinen Sinn... aber so sind C und C++ unsigned
semantisch tatsächlich funktioniert.
Die tatsächliche Verwendung eines unsigned
Typ für die Größe von Containern ist ein Designfehler von C++ und leider sind wir nun dazu verdammt, diese falsche Wahl für immer zu verwenden (aus Gründen der Abwärtskompatibilität). Man mag den Namen "unsigned" mögen, weil er ähnlich wie "non-negative" ist, aber der Name ist irrelevant und was zählt, ist die Semantik... und unsigned
ist sehr weit von "nicht-negativ" entfernt.
Aus diesem Grund bevorzuge ich persönlich bei der Codierung der meisten Schleifen über Vektoren die Form:
for (int i=0,n=v.size(); i<n; i++) {
...
}
(natürlich unter der Annahme, dass sich die Größe des Vektors während der Iteration nicht ändert und dass ich den Index tatsächlich im Körper benötige, da sonst die for (auto& x : v)...
ist besser).
Dieses Weglaufen von unsigned
und die Verwendung einfacher Ganzzahlen hat den Vorteil, dass die Fallen vermieden werden, die eine Folge der unsigned size_t
Designfehler. Betrachten Sie zum Beispiel:
// draw lines connecting the dots
for (size_t i=0; i<pts.size()-1; i++) {
drawLine(pts[i], pts[i+1]);
}
der obige Code wird Probleme haben, wenn die pts
Vektor leer ist, weil pts.size()-1
ist in diesem Fall eine große unsinnige Zahl. Der Umgang mit Ausdrücken, bei denen a < b-1
ist nicht dasselbe wie a+1 < b
selbst für häufig verwendete Werte ist wie ein Tanz in einem Minenfeld.
Historisch gesehen ist die Rechtfertigung für size_t
unsigned ist für die Möglichkeit, die zusätzlichen Bits für die Werte zu verwenden, z. B. 65535 Elemente in Arrays statt nur 32767 auf 16-Bit-Plattformen zu haben. Meiner Meinung nach waren die zusätzlichen Kosten für diese falsche semantische Wahl schon damals den Gewinn nicht wert (und wenn 32767 Elemente jetzt nicht ausreichen, dann werden 65535 sowieso nicht mehr lange ausreichen).
Vorzeichenlose Werte sind großartig und sehr nützlich, aber NICHT für die Darstellung der Containergröße oder für Indizes; für Größe und Index funktionieren reguläre vorzeichenbehaftete Ganzzahlen viel besser, weil die Semantik das ist, was man erwarten würde.
Werte ohne Vorzeichen sind der ideale Typ, wenn Sie die arithmetische Eigenschaft modulo benötigen oder auf Bitebene arbeiten wollen.