Comment puis-je attribuer un std :: string sur la pile en utilisant la mise en œuvre de chaîne de glibc?

StackOverflow https://stackoverflow.com/questions/783944

Question

int main(void)
{
   std::string foo("foo");
}

Ma compréhension est que le code ci-dessus utilise l'allocateur par défaut pour appeler de nouveau. Ainsi, même si la chaîne std :: foo est allouée sur la pile la mémoire tampon interne à l'intérieur de foo est alloué sur le tas.

Comment puis-je créer une chaîne qui est entièrement allouée sur la pile?

Était-ce utile?

La solution

Je voulais le faire moi-même récemment et trouvé le code suivant éclairante:

de stack_container.h de le chrome

Il définit une nouvelle std::allocator qui peut fournir l'allocation basée sur la pile pour l'attribution initiale de stockage pour les conteneurs STL. Je liquidée trouver une autre façon de résoudre mon problème particulier, donc je n'ai pas utilisé en fait le code moi-même, mais peut-être que ce sera utile pour vous. Ne prenez soin de lire les commentaires dans le code concernant l'utilisation et mises en garde.

Pour ceux qui ont mis en doute l'utilité et la santé mentale de le faire, pensez à:

  • Très souvent, vous savez a priori que votre chaîne a une taille maximale raisonnable. Par exemple, si la chaîne va stocker un entier de 32 bits décimal formaté, vous savez que vous n'avez pas besoin de plus de 11 caractères pour le faire. Il n'y a pas besoin d'une chaîne qui peut dynamiquement atteindre une taille illimitée dans ce cas.
  • Allouer de la pile est plus rapide dans de nombreux cas que l'allocation du tas.
  • Si la chaîne est créé et détruit fréquemment (supposons qu'il est une variable locale dans une fonction d'utilité courante), l'attribution de la pile au lieu du tas évitera désabonnement induisant la fragmentation dans le allocateur de tas. Pour les applications qui utilisent beaucoup de mémoire, cela pourrait être un changeur de jeu.

Certaines personnes ont fait remarquer qu'une chaîne qui utilise l'allocation basée sur la pile ne sera pas un std::string comme si cela diminue en quelque sorte son utilité. Il est vrai que vous ne pouvez pas utiliser les deux de façon interchangeable, de sorte que vous ne serez pas en mesure de passer votre stackstring aux fonctions qui attendent un std::string. Mais (si vous le faites à droite), vous serez en mesure d'utiliser toutes les mêmes fonctions membres de votre stackstring que vous utilisez maintenant std::string, comme find_first_of(), append(), etc. begin() et end() sera toujours fonctionner correctement, vous serez en mesure d'utiliser la plupart des algorithmes de STL. Bien sûr, il ne sera pas std::string dans le sens le plus strict, mais il sera toujours une « chaîne » dans le sens pratique, et il sera toujours très utile.

Autres conseils

Le problème est que std::basic_string a un paramètre de modèle pour l'allocateur. Mais std::string n'est pas un modèle et n'a pas de paramètres.

Alors, vous pourriez, en principe, utiliser une instanciation de std::basic_string avec un allocateur qui utilise la mémoire sur la pile, mais ce ne serait pas un std::string. En particulier, vous ne seriez pas obtenir le polymorphisme d'exécution, et vous ne pouviez pas passer les objets résultant en fonctions attendant un std::string.

Vous ne pouvez pas. Sauf que ...

std::string est une instanciation de

std::basic_string<class CharType, 
                  class Traits=char_traits<CharType>, 
                  class Allocator=allocator<CharType> >

Vous pourriez peut définir une classe Allocataire qui utilise alloca pour la gestion de la mémoire. Cela ne fonctionnera que si l'allocateur lui-même, et les méthodes de basic_string qui l'invoquent, sont directement ou indirectement tous inline. Un objet basic_string créé avec cette allocateur ne serait pas être un std::string, mais il se comporterait (la plupart du temps) comme elle. Cependant, ce serait une bonne quantité de travail pour des gains limités. Plus précisément, en utilisant cette classe pour renvoyer des valeurs d'une fonction serait un obstacle à l'avancement.

Je ne sais pas pourquoi vous ou quelqu'un d'autre voulez faire.

Je pense que faire une telle chose serait difficile à faire, je me demande pourquoi vous voulez le faire? Pour allouer quelque chose d'entièrement sur la pile, le compilateur a besoin de savoir au moment de la compilation ce que la taille exacte de la chose est - dans votre exemple, il aurait besoin de connaître non seulement la taille des métadonnées de std::string, mais aussi la taille des données de chaîne lui-même. Ce n'est pas trop souple, vous auriez probablement besoin de différents types de chaîne en fonction de la taille des données de chaîne que vous êtes désireux d'y inclure - pas qu'il serait impossible de le faire, il suffit aurait tendance à compliquer les choses un peu.

  • std :: string sera toujours gérer son stockage interne avec de nouveaux / supprimer.
  • Je ne sais pas pourquoi votre question contient La mise en œuvre de la chaîne de glibc . La mise en œuvre de chaîne de c ++ bibliothèque standard n'a rien à voir avec glibc .
  • La seule façon de stocker une chaîne sur la pile est d'utiliser un tableau C char sur la pile (comme ce Shhnap décrit). Mais c'est probablement pas ce que vous voulez quand même: -)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top