web-dev-qa-db-fra.com

Prepend std :: string

Quelle est la manière la plus efficace de faire précéder std::string? Cela vaut-il la peine d'écrire une fonction entière pour cela, ou cela ne prendrait-il que 1 à 2 lignes? Je ne vois rien de lié à un std::string::Push_front.

48
zeboidlund

Il existe en fait une fonction similaire à celle qui n'existe pas std::string::Push_front, voir l'exemple ci-dessous.


Documentation de std :: string :: insert

#include <iostream>
#include <string>

int
main (int argc, char *argv[])
{
  std::string s1 (" world");
  std::string s2 ("Ello");

  s1.insert (0,     s2); // insert the contents of s2 at offset 0 in s1
  s1.insert (0, 1, 'h'); // insert one (1) 'h'        at offset 0 in s1

  std::cout << s1 << std::endl;
}

sortie:

hello world

Étant donné que l'ajout d'une nouvelle chaîne à des données peut nécessiter à la fois une réallocation et une copie/déplacement des données existantes, vous pouvez obtenir certains avantages en termes de performances en vous débarrassant de la partie de réallocation en utilisant std::string::reserve (pour allouer plus de mémoire avant la main).

La copie/le déplacement de données est malheureusement assez inévitable, à moins que vous ne définissiez votre propre classe sur mesure qui agit comme std::string qui alloue une grande mémoire tampon et place le premier contenu au centre de cette mémoire tampon.

Ensuite, vous pouvez à la fois ajouter et ajouter des données sans réallocation ni déplacement de données, si le tampon est suffisamment grand. La copie de la source vers la destination est toujours, bien sûr, requise.


Si vous avez un tampon dans lequel vous savez que vous ajouterez des données plus souvent que vous ajouterez une bonne alternative est de stocker la chaîne en arrière et de l'inverser si nécessaire (si c'est plus rare).

70
myString.insert(0, otherString);

Laissez les rédacteurs de la bibliothèque de modèles standard se soucier de l'efficacité; profiter de toutes leurs heures de travail plutôt que de reprogrammer la roue.

De cette façon, les deux.

Tant que l'implémentation STL que vous utilisez a été pensée, vous disposerez d'un code efficace. Si vous utilisez une STL mal écrite, vous avez quand même de plus gros problèmes :)

6
matiu

Si vous utilisez std::string::append, vous devez réaliser que ce qui suit est équivalent:

std::string lhs1 = "hello ";
std::string lh2 = "hello ";
std::string rhs = "world!";

lhs1.append(rhs);
lhs2 += rhs; // equivalent to above
// Also the same:
// lhs2 = lhs + rhs;

De même, un "pré-ajout" serait équivalent à ce qui suit:

std::string result = "world";
result = "hello " + result;
// If prepend existed, this would be equivalent to
// result.prepend("hello");

Vous devez cependant noter qu'il est plutôt inefficace de faire ce qui précède.

5
Mike Bailey

Il y a une string operator+ (char lhs, const string& rhs); surchargée, vous pouvez donc simplement faire your_string 'a' + your_string imiter Push_front.

Ce n'est pas en place mais crée une nouvelle chaîne, alors ne vous attendez pas à ce qu'elle soit efficace. Pour une solution (probablement) plus efficace, utilisez resize pour rassembler de l'espace, std::copy_backward pour reculer d'une chaîne toute la chaîne et insérer le nouveau caractère au début.

3
Alexander Gessler