2009-10-20 21 views
5

Recentemente ho notato che la seguente affermazione non è vera data std::string s.Perché non è std :: string :: max_size() == std :: string :: allocator :: max_size()

s.max_size() == s.get_allocator().max_size(); 

Trovo che questo sia interessante, per impostazione predefinita std::string utilizzerà std::allocator<char> che ha un limite teorico di size_type(-1) (sì lo so sto assumendo complemento a 2, ma che è estraneo alla domanda reale). So che i limiti pratici saranno significativamente inferiori a questo. Su un tipico sistema x86 a 32 bit, il kernel occuperà 2 GB (forse 1 GB) dello spazio degli indirizzi, lasciando un limite superiore pratico molto più piccolo.

In ogni caso, lo std::basic_string<>::max_size() di GNU libstdC++ sembra restituire lo stesso valore indipendentemente da ciò che dice l'allocatore utilizzato (qualcosa come 1073741820).

Quindi la domanda rimane, perché std::basic_string<>::max_size() non restituisce semplicemente get_allocator().max_size()? Mi sembra che questo sia l'ipotetico limite superiore. E se l'allocazione arriva a breve, si limiterà a lanciare un std::bad_alloc, quindi perché non provare?

Questa è più di una curiosità che altro, mi chiedevo solo perché i due sono definiti separatamente in almeno questa implementazione.

+0

"E se. l'allocazione viene a mancare, si limiterà a lanciare uno std :: bad_alloc, quindi perché non provare? "Posso rispondere per te. Le persone potrebbero aver bisogno di elaborare stringhe di grandi dimensioni e dividerle in grossi blocchi di stringhe e, se non possono realmente dipendere da ciò che max_size gli segnala, dovranno ricorrere a limitazioni ad-hoc. – GManNickG

+0

Vedo il tuo punto, ma non sono d'accordo. La realtà è che si deve sempre presumere che qualsiasi dimensione di stringa <= 'max_size()' abbia la possibilità di fallire perché dipende da una variabile esterna (quanto è disponibile nell'heap). –

+0

concordato. Il mio unico punto è che dovrebbero almeno cercare di essere precisi, non solo dare un grande numero e sperare per il meglio. Dai un numero concreto una speranza per il meglio. :) Domanda difficile, però. – GManNickG

risposta

10

In Microsoft Connect è stato postato un bug relativo alla tua domanda. Microsoft ha una risposta interessante:

L'abbiamo risolto come in base alla nostra interpretazione dello standard, che non spiega chiaramente quale sia lo scopo previsto per max_size(). Allocator max_size() è descritto come "il valore più grande che può essere passato a X: allocate()" (C++ 03 20.1.5 [lib.allocator.requirements]/Table 32), ma il contenitore max_size() è descritto come "size() del più grande contenitore possibile" (23.1 [lib.container.requirements]/Tabella 65). Niente descrive se o come il contenitore max_size() debba essere derivato da allocator max_size(). La nostra implementazione per molti anni ha derivato il contenitore max_size() direttamente dall'assegnatore max_size() e quindi ha utilizzato questo valore per i controlli di overflow e così via. Altre interpretazioni dello Standard, come la tua, sono possibili, ma non sono corrette in modo inequivocabile. La formulazione dello standard potrebbe sicuramente beneficiare di chiarimenti qui. A meno che e fino a quando ciò non accada, abbiamo deciso di lasciare invariata la nostra attuale implementazione per due motivi: (1) altri clienti potrebbero dipendere dal nostro comportamento attuale e (2) max_size() fondamentalmente non compra nulla. Al massimo, le cose che consumano gli allocatori (come i contenitori) potrebbero usare l'allocatore max_size() per prevedere quando allocate() fallirà - ma semplicemente chiamare allocate() è un test migliore, dato che l'allocatore deciderà quindi di distribuire la memoria o meno. Le cose che consumano contenitori potrebbero usare container max_size() come garanzia di quanto potrebbe essere large size(), ma una garanzia più semplice è l'intervallo size_type.

Inoltre here è possibile trovare il numero principale # 197. Il comitato ha preso in considerazione la richiesta di migliorare la formulazione dello standard, ma è stato rifiutato.

Quindi la risposta alla tua domanda "Perché ..?"è che Standard non spiega chiaramente quale sia lo scopo previsto per max_size().

4

Non sono completamente sicuro, ma per quanto ne so, lo std::basic_string non è limitato nello standard corrente per memorizzare la stringa in memoria continua. Ad esempio, può memorizzarlo in diversi blocchi. Ciascun blocco di questo tipo viene quindi limitato a std::allocator::max_size() ma la somma potrebbe essere maggiore di quella.

Anche sembra essere il caso con i contenitori STL. E dopo tutto std::basic_string è un contenitore.

+0

Tranne che nessuno probabilmente lo implementa in questo modo, lo standard successivo potrebbe non consentirlo (non del tutto sicuro), e l'OP sta vedendo che è significativamente * più piccolo * di quanto consentito dall'allocatore. – UncleBens

1

L'implementazione di GCC ha un commento su come calcolano max_size (si deve sottrarre la dimensione dell'oggetto di manutenzione interno che viene allocata come blocco singolo con la stringa), e quindi aggiunge che max_size() restituisce un quarto di quello.Non vi è alcuna motivazione fornita, quindi forse è solo un margine di sicurezza? (Dovrebbe anche fornire una classe corda, che forse si dovrebbe usare per stringhe così grandi?)

con VC++ max_size() restituisce uno in meno rispetto allocator.max_size() - probabilmente per tenere conto per la terminazione carattere null

Problemi correlati