2009-10-20 15 views
5

Récemment, j'ai remarqué que l'instruction suivante n'est pas vraie étant donné std::string s.Pourquoi std :: string :: max_size() == std :: string :: allocator :: max_size()

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

Je trouve cela intéressant, par défaut std::string utilisera std::allocator<char> qui a une limite théorique de size_type(-1) (oui je sais je suppose que le complément de 2, mais c'est sans rapport avec la question réelle). Je sais que les limites pratiques seront beaucoup moins importantes. Sur un système x86 32 bits typique, le noyau occupera 2 Go (peut-être 1 Go) de l'espace d'adressage, ce qui laisse une limite supérieure pratique beaucoup plus petite.

Quoi qu'il en soit, le std::basic_string<>::max_size() de GNU libstdC++ semble retourner la même valeur indépendamment de ce que dit l'allocateur qu'il utilise (quelque chose comme 1073741820).

Donc la question demeure, pourquoi ne pas std::basic_string<>::max_size() juste retourner get_allocator().max_size()? Il me semble que c'est la limite supérieure hypothétique. Et si l'allocation est courte, il faudra juste lancer un std::bad_alloc, alors pourquoi ne pas essayer?

Ceci est plus d'une curiosité que toute autre chose, je me demandais juste pourquoi les deux sont définis séparément dans au moins cette mise en œuvre.

+0

« Et si. l'allocation arrive à court, il va juste lancer un std :: bad_alloc, alors pourquoi ne pas essayer? "Je peux répondre à cela pour vous. Les utilisateurs peuvent avoir besoin de traiter des chaînes de caractères volumineuses et de les diviser en segments de chaînes de caractères volumineux, et s'ils ne peuvent pas réellement dépendre des rapports max_size, ils devront recourir à des limitations ad-hoc. – GManNickG

+0

Je vois ce que vous voulez dire, mais je ne suis pas d'accord. La réalité est que vous devez toujours supposer que toute taille de chaîne <= 'max_size()' a la possibilité d'échouer car elle dépend d'une variable externe (combien est disponible dans le tas). –

+0

D'accord. Mon seul point est qu'ils devraient au moins essayer d'être précis, pas seulement donner un grand nombre et espérer le meilleur. Donnez un nombre pratique d'espoir pour le meilleur. :) Question difficile, cependant. – GManNickG

Répondre

10

Dans Microsoft Connect a été posté bug lié à votre question. Microsoft a une réponse intéressante:

Nous l'avons résolu en tant que By Design selon notre interprétation de la norme, ce qui n'explique pas clairement quel est le but de max_size(). Allocator max_size() est décrit comme "la plus grande valeur qui peut significativement être passée à X :: allocate()" (C++ 03 20.1.5 [lib.allocator.requirements]/Table 32), mais le conteneur max_size() est décrit comme "size() du plus grand conteneur possible" (23.1 [lib.container.requirements]/Table 65). Rien ne décrit si ou comment le conteneur max_size() doit être dérivé de l'allocateur max_size(). Notre implémentation depuis de nombreuses années a dérivé le conteneur max_size() directement à partir de l'allocateur max_size() et a ensuite utilisé cette valeur pour les vérifications de débordement et ainsi de suite. D'autres interprétations de la norme, comme la vôtre, sont possibles, mais ne sont pas sans équivoque pour nous. Le libellé de la norme pourrait certainement bénéficier d'une clarification ici. À moins que cela ne se produise, nous avons décidé de laisser notre implémentation actuelle inchangée pour deux raisons: (1) les autres clients peuvent dépendre de notre comportement actuel, et (2) max_size() n'achète fondamentalement rien. Tout au plus, les éléments qui consomment des allocateurs (comme des conteneurs) peuvent utiliser allocator max_size() pour prédire quand allocate() échouera - mais appeler simplement allocate() est un meilleur test puisque l'allocateur décidera alors de donner de la mémoire ou non. Les choses qui consomment des conteneurs peuvent utiliser le conteneur max_size() pour garantir la taille de size(), mais une garantie plus simple est la portée de size_type.

En outre here vous pourriez trouver le problème de base # 197. Le comité a examiné la demande d'amélioration de la formulation de Standard, mais celle-ci a été refusée.

Donc la réponse à votre question "Pourquoi ..?"est-ce standard ne pas expliquer clairement ce que l'intention est pour max_size()

4

Je ne suis pas entièrement sûr mais pour autant que je sais std::basic_string n'est pas limité dans la norme actuelle pour stocker la chaîne en mémoire continue. Par exemple, il peut le stocker en plusieurs morceaux. Chaque segment est alors limité à std::allocator::max_size() mais la somme peut être plus grande que cela.

Cela semble également être le cas avec les conteneurs STL. Et après tout std::basic_string est un conteneur.

+0

Sauf que personne ne l'implémente probablement de cette façon, le prochain standard ne l'autorisera peut-être pas (pas entièrement sûr), et l'OP voit qu'il est significativement * plus petit * que ce que permet l'allocateur. – UncleBens

1

L'implémentation de GCC a un commentaire comment ils calculent max_size (on doit soustraire la taille de l'objet interne interne qui est allouée comme un seul bloc avec la chaîne), puis ajoute que max_size() renvoie un quart de cela.Il n'y a pas de justification donnée, alors peut-être que c'est juste une marge de sécurité? (Il devrait également fournir une classe de corde, que peut-on utiliser pour les grandes chaînes?)

Avec max_size() rendements VC un de moins que allocator.max_size() - sans doute pour tenir compte de caractère nul