2015-02-23 22 views
7

La mia comprensione di size_t è che sarà abbastanza grande da contenere qualsiasi valore (intero) che ci si potrebbe aspettare che sia necessario tenere. (Forse si tratta di una spiegazione scarsa?)C++: C'è qualche motivo per usare uint64_t invece di size_t

Ad esempio, se si stesse utilizzando qualcosa come un ciclo for per scorrere tutti gli elementi di un vettore, size_t sarebbe in genere lungo 64 bit (o almeno sul mio sistema) in ordina che possa contenere tutti i possibili valori di ritorno da vector.size().

O almeno, penso che sia corretto?

Pertanto, non v'è alcun motivo di usare A piuttosto che B:

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

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

se ho sbagliato con la mia spiegazione o avete una spiegazione migliore, non esitate a modificare.

Edit: Devo aggiungere che la mia comprensione è che size_t si comporta come un normale intero senza segno, forse non è corretto?

+0

se avete bisogno di una garanzia che il vostro int sarà 64 bit per qualsiasi motivo (di solito la manipolazione dei byte). 'size_t' può variare a seconda del sistema e delle opzioni di compilazione –

+0

' size_t' non è garantito per essere 64 bit – dtech

+0

Se si utilizza 'uint64_t' su un target a 32 bit è possibile ottenere prestazioni non ottimali. – sharptooth

risposta

3

Il caso corretto sarebbe for(std::vector::size_type i ....

Ai fini di iterazione attraverso un vettore, o qualcosa del genere, si sarebbe difficile trovare un caso in cui size_t non è abbastanza grande, e uint64_t è,

Naturalmente, su un 32 -bit macchina, size_t sarebbe in genere 32 bit, ma si consiglia di trattare con numeri superiori a 4 miliardi, che richiederebbe più di 32 bit, e questo è certamente un caso d'uso per uint64_t. In altre parole, uint64_t è garantito per essere 64-bit, size_t non è 64 bit in tutte le macchine/architetture.

8

size_t è il tipo di ritorno sizeof.

Lo standard dice che è un typedef di un tipo intero senza segno e abbastanza grande da contenere la dimensione di qualsiasi oggetto possibile.
Tuttavia, non specifica se è più piccolo, più grande o della stessa dimensione di uint64_t (un typedef per un numero intero senza segno a 64 bit a larghezza fissa), né in quest'ultimo caso se è dello stesso tipo.

Quindi, utilizzare size_t dove semanticamente corretto.
Come per il size() di un std::vector<T> (std::vector ottiene è size_type dalla allocatore usato, std::allocator<T> utilizzando size_t).

+0

Senza offesa, ma 'std :: vector :: size()' restituisce 'std :: vector :: size_type' – Nick

+0

Sì, e viene fornito dall'allocatore. – Deduplicator

5

uint64_t è garantito per essere 64 bit. Se hai bisogno di 64 bit, dovresti usarlo

size_t non è garantito per essere 64 bit, potrebbe essere 128 bit in una macchina del futuro. Quindi, la parola chiave uint_64 è riservata da questo :)

+0

dovrebbe essere "garantito TO" – dtech

2

std::size_t è definito come un tipo intero senza segno. La sua lunghezza dipende dalla piattaforma. v.size() restituirà sempre un valore di tipo std::size_t, quindi l'opzione B è sempre corretta.

2

No, size_t non ha assolutamente alcuna connessione a "contenere qualsiasi valore intero che ci si potrebbe aspettare che sia necessario tenere". Dove lo hai preso?

size_t dovrebbe essere abbastanza grande da contenere la dimensione in byte di qualsiasi oggetto continuo nella specifica implementazione. Concettualmente, questo è molto meno di "qualsiasi valore intero". La lingua non garantisce che sia permesso creare oggetti che occupano l'intera memoria indirizzabile, il che significa che size_t non è concettualmente nemmeno abbastanza da contenere il numero di byte indirizzabili di memoria.

Se si desidera associare "qualsiasi valore intero" alla dimensione della memoria, il tipo appropriato sarà uintptr_t, che è concettualmente più grande di size_t. Ma non vedo alcuna ragione per legare "qualsiasi valore intero" alle caratteristiche della memoria. Per esempio. anche se uintptr_t è maggiore di size_t, non è garantito che sia sufficientemente grande da contenere la dimensione del file più grande nel file system della piattaforma.

Il motivo per cui è possibile utilizzare lo size_t per iterare sugli elementi di std::vector è che il vettore è basato internamente su un array. Le matrici sono oggetti continui, motivo per cui le loro dimensioni sono coperte da size_t. Ma una volta preso in considerazione un contenitore non contiguo, come std::list, non è più garantito che size_t sia sufficiente per misurare o indicizzare tali contenitori.

uint64_t può essere maggiore di size_t. Ma è del tutto possibile che tu possa dover lavorare con valori interi che non rientrano in uint64_t.

+0

'std :: malloc' e' std :: allocator' usano anche 'std :: size_t'. – tmlen

+0

Anche 'uintptr_t' potrebbe essere troppo piccolo. Dato che non ci sono limiti per i valori nella descrizione degli OP ... – Deduplicator

+0

@tmlen: Fanno perché allocano * blocchi * continui di memoria, cioè allocano array di byte. Per loro è perfettamente appropriato usare 'size_t'. – AnT