2015-02-23 6 views
7

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?)C++: Gibt es irgendeinen Grund, uint64_t anstelle von size_t zu verwenden?

Zum Beispiel, wenn Sie so etwas wie eine for-Schleife wurden alle Elemente in einem Vektor iterieren, size_t typischerweise 64 Bit lang sein würde (oder zumindest auf meinem System) in Reihenfolge, dass es alle möglichen Rückgabewerte von vector.size() enthalten kann.

Oder zumindest, ich denke, das ist richtig? Daher

, gibt es keinen Grund ein eher zu verwenden als B:

A: for(uint64_t i = 0; i < v.size(); ++ i)

B: for(size_t i = 0; i < v.size(); ++ i)

Wenn ich falsch mit meiner Erklärung, oder Sie haben eine bessere Erklärung, Bitte zögern Sie nicht zu bearbeiten.

Edit: 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?

+0

Wenn Sie eine harte Garantie benötigen, dass Ihr int 64 Bit aus irgendeinem Grund (in der Regel Byte-Manipulation) sein wird. 'size_t' kann je nach System und Kompilierungsoptionen variieren. –

+0

' size_t' garantiert nicht 64bit – dtech

+0

Wenn Sie 'uint64_t' auf einem 32-Bit-Ziel verwenden, können Sie eine Leistung erzielen, die weit von der optimalen entfernt ist. – sharptooth

Antwort

3

Der korrekte Fall wäre for(std::vector::size_type i ....

Für die Zwecke durch einen Vektor von iterieren, oder etwas in der Art, würden Sie hart gedrückt werden, um einen Fall zu finden, wo size_t nicht groß genug ist, und uint64_t sind,

Natürlich auf einem 32 -Bit-Maschine, size_t würde in der Regel 32 Bit sein, aber Sie können mit Zahlen größer als 4 Milliarden befassen, die mehr als 32 Bit erfordern würde, und dies ist sicherlich ein Anwendungsfall für uint64_t. Mit anderen Worten, uint64_t ist garantiert 64-Bit, size_t ist nicht 64 Bit in allen Maschinen/Architekturen.

8

size_t ist der Rückgabetyp sizeof.

Der Standard sagt, es ist ein Typedef von einem unsigned Integer-Typ und groß genug, um die Größe eines möglichen Objekts zu halten.
Aber es mandatiert nicht, ob es kleiner, größer oder die gleiche Größe wie uint64_t (ein Typedef für eine 64-Bit-Ganzzahl mit fester Breite ohne Vorzeichen), noch im letzteren Fall, ob es der gleiche Typ ist.

Also verwenden size_t wo semantisch korrekt.
Wie für die size() ein std::vector<T> (std::vector bekommt es size_type vom verwendeten allocator, std::allocator<T> mit size_t).

+0

Nichts für ungut, aber 'std :: vector :: size()' gibt 'std :: vector zurück :: size_type' – Nick

+0

Ja, und das kommt vom Zuordner. – Deduplicator

5

uint64_t ist garantiert für 64 Bit. Wenn Sie 64 Bits benötigen, sollten Sie es verwenden

size_t ist nicht garantiert für 64 Bit, könnte 128 Bits in einer zukünftigen Maschine sein. Also, Stichwort uint_64 ist davon reserviert :)

+0

sollte "garantiert sein" – dtech

2

std::size_t ist als vorzeichenloser Integer-Typ definiert. Seine Länge hängt von der Plattform ab. v.size() gibt immer einen Wert vom Typ std::size_t zurück, daher ist Option B immer korrekt.

2

Nein, size_t hat absolut keine Verbindung zu "hält irgendeinen ganzzahligen 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. Konzeptionell 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, um die Anzahl der adressierbaren Speicherbytes zu halten.

Wenn Sie "Any Integer value" an die Speichergröße binden möchten, wäre der entsprechende Typ uintptr_t, was konzeptionell größer als size_t ist. Aber ich sehe keinen Grund, irgendeinen ganzzahligen Wert an die Speichereigenschaften zu binden. Z.B. Auch wenn 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 std::vector Elemente zu iterieren, ist, dass Vektor intern auf einem Array basiert. Arrays sind kontinuierliche Objekte, weshalb ihre Größen von size_t abgedeckt werden. Aber sobald Sie einen nicht-zusammenhängenden Container in Betracht ziehen, wie std::list, size_t ist nicht mehr garantiert, dass es ausreichend ist, solche Container zu messen oder zu indizieren.

uint64_t kann einfacher größer als size_t sein. Es ist jedoch durchaus möglich, dass Sie mit Integer-Werten arbeiten müssen, die nicht in uint64_t passen.

+0

'std :: malloc' und' std :: allocator' verwenden auch 'std :: size_t'. – tmlen

+0

Selbst 'uintptr_t' könnte zu klein sein. Da es keine Begrenzung für die Werte in der OP-Beschreibung gibt ... – Deduplicator

+0

@tmlen: Sie tun, weil sie * kontinuierliche * Speicherblöcke zuordnen, d. H. Sie ordnen Byte-Arrays zu. Für sie ist es durchaus angemessen, 'size_t' zu verwenden. – AnT

Verwandte Themen