Mein Verständnis von size_t
ist, dass es groß genug sein wird, um irgendeinen (ganzzahligen) Wert zu halten, von dem Sie erwarten, dass er gehalten wird. (Vielleicht ist das eine schlechte Erklärung?)
Wenn Sie beispielsweise so etwas wie eine for-Schleife verwenden, um über alle Elemente in einem Vektor zu iterieren, wäre size_t
typischerweise 64 Bit lang (oder zumindest auf meinem System), damit es alle möglichen Returns enthalten kann Werte von vector.size ().
Oder zumindest, ich denke, das ist richtig?
Gibt es deshalb einen Grund, A statt B zu verwenden?
A: for(uint64_t i = 0; i < v.size(); ++ i)
B: for(size_t i = 0; i < v.size(); ++ i)
Wenn ich mit meiner Erklärung falsch liege oder Sie eine bessere Erklärung haben, können Sie sie gerne bearbeiten.
Bearbeiten: Ich sollte hinzufügen, dass mein Verständnis ist, dass size_t
verhält sich wie eine normale vorzeichenlose ganze Zahl - vielleicht ist das nicht korrekt?
size_t
ist der Rückgabetyp von sizeof
.
Der Standard sagt, es ist ein Typedef von einem vorzeichenlosen Integer-Typ und groß genug, um die Größe eines möglichen Objekts zu halten.
Es wird jedoch nicht festgelegt, ob es kleiner, größer oder gleich groß wie uint64_t
ist (ein Typdef für eine 64-Bit-Ganzzahl ohne Vorzeichen mit fester Breite), und im letzteren Fall ist es nicht derselbe Typ.
Daher verwenden size_t
semantisch korrekt.
Wie für size()
von std::vector<T>
( std::vector
erhält size_type
vom verwendeten Zuordner, std::allocator<T>
mit size_t
).
Der korrekte Fall wäre for(std::vector::size_type i ...
.
Für den Zweck der Iteration durch einen Vektor oder etwas dieser Art wäre es schwierig, einen Fall zu finden, in dem size_t
nicht groß genug ist und uint64_t
ist,
Natürlich wäre size_t
auf einer 32-Bit-Maschine normalerweise 32 Bit, aber Sie möchten vielleicht mit Zahlen umgehen, die größer als 4 Milliarden sind, was mehr als 32 Bit erfordern würde. Fall für uint64_t
. Mit anderen Worten, uint64_t
ist garantiert 64-Bit, size_t
ist nicht 64 Bits in allen Maschinen / Architekturen.
Nein, size_t
hat absolut keine Verbindung zu "hält irgendeinen Integer-Wert, von dem Sie erwarten, dass er gehalten werden muss". Woher hast du das?
size_t
soll groß genug sein, um die Byte-Größe jedes kontinuierlichen Objekts in der gegebenen Implementierung zu halten. Vom Konzept her ist dies weit weniger als "irgendein ganzzahliger Wert". Die Sprache garantiert nicht, dass Sie Objekte erstellen dürfen, die den gesamten adressierbaren Speicher belegen, was bedeutet, dass size_t
konzeptionell nicht einmal ausreicht, die Anzahl der adressierbaren Speicherbytes zu halten.
Wenn Sie "irgendeinen ganzzahligen Wert" an die Speichergröße binden wollten, wäre der entsprechende Typ uintptr_t
, was konzeptionell größer ist als size_t
. Aber ich sehe keinen Grund, irgendeinen ganzzahligen Wert an die Speichereigenschaften zu binden. Z.B. Obwohl uintptr_t
größer als size_t
ist, ist es nicht garantiert, dass es groß genug ist, um die Größe der größten Datei im Dateisystem Ihrer Plattform zu speichern.
Der Grund, warum Sie size_t
verwenden können, um über die Elemente von std::vector
zu iterieren, ist, dass der Vektor intern auf einem Array basiert. Arrays sind kontinuierliche Objekte, weshalb ihre Größen von size_t
abgedeckt sind. Wenn Sie jedoch einen nicht zusammenhängenden Container wie std::list
, size_t
berücksichtigen, reicht dies nicht mehr aus, um solche Container zu messen oder zu indizieren.
uint64_t
kann einfacher größer sein als size_t
. Es ist aber durchaus möglich, dass Sie mit Integer-Werten arbeiten müssen, die nicht in uint64_t
passen.