77 votes

Prédire std::string

Quel est le moyen le plus efficace de précéder std::string ? Cela vaut-il la peine d'écrire une fonction entière pour le faire, ou cela ne prendrait-il qu'une ou deux lignes ? Je ne vois rien qui soit lié à une std::string::push_front .

5 votes

Une raison pour laquelle vous ne pouvez pas faire quelque chose comme s = a + s ?

0 votes

Qu'est-ce que tu veux dire par "prepend" ? Est-ce que c'est ce que @MikeBantegui a mentionné ? ou vous essayez de faire quelque chose d'autre ?

0 votes

Prépendre à une chaîne de caractères ne va pas être efficace, peut-être serait-il préférable d'ajouter à la chaîne de caractères et de l'inverser lorsque vous avez terminé ?

110voto

Filip Roséen - refp Points 24995

Il existe en fait une fonction similaire à l'inexistant 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 de données au début d'une chaîne de caractères peut nécessiter à la fois une réaffectation et une copie/déplacement des données existantes, vous pouvez obtenir des gains de performances en vous débarrassant de la partie réaffectation en utilisant std::string::reserve (pour allouer plus de mémoire à l'avance).

Le copier/déplacer de données est malheureusement inévitable, à moins que vous ne définissiez votre propre classe personnalisée qui agisse comme std::string qui alloue un grand tampon et place le premier contenu au centre de ce tampon mémoire.

Vous pouvez alors ajouter et ajouter des données sans réaffectation ni déplacement de données, à condition que le tampon soit suffisamment grand. La copie de source a destination est toujours, évidemment, nécessaire.


Si vous avez un tampon dans lequel vous savez que vous allez Préparez données plus souvent que vous ajouter une bonne alternative est de stocker la chaîne à l'envers, et de l'inverser en cas de besoin (si cela est plus rare).

16voto

matiu Points 2168
myString.insert(0, otherString);

Laissez les rédacteurs de la bibliothèque de modèles standard s'occuper de l'efficacité ; mettez à profit toutes leurs heures de travail plutôt que de reprogrammer la roue.

Cette méthode fait les deux.

Tant que l'implémentation de la STL que vous utilisez a été réfléchie, vous aurez un code efficace. Si vous utilisez une STL mal écrite, vous aurez de toute façon de plus gros problèmes :)

16 votes

Un algorithme inefficace ne peut être sauvé par une mise en œuvre intelligente.

7voto

Mike Bantegui Points 5740

Si vous utilisez std::string::append vous devez comprendre que ce qui suit est équivalent :

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

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

De même, un "prepend" serait équivalent à ce qui suit :

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

Il convient de noter qu'il est plutôt inefficace de faire ce qui précède.

9 votes

Quelqu'un sait-il pourquoi cette réponse a été rétrogradée ? Ses affirmations sont-elles incorrectes d'une manière ou d'une autre ? Qu'est-ce que nous, lecteurs dans 5 ans, sommes censés déduire des votes négatifs inexpliqués ? Cela n'aide personne. Quelqu'un peut-il enfin élaborer ?

3 votes

@underscore_d Comme mentionné dans une autre réponse, l'utilisation de operator+ devra créer une copie de la chaîne. En revanche, l'utilisation de insert() peut fonctionner in-place (enfin, après avoir éventuellement réalloué le tampon de chaîne). Cela n'a pas d'importance pour ces petits exemples, mais cela peut en avoir pour des chaînes de caractères énormes. Avec C++11, il est également possible de dire "result = "hello " + std::move(result)` afin d'éviter la copie.

1 votes

@amon Merci ! Cela semble évident maintenant, après deux ans d'apprentissage et après que vous l'ayez signalé, mais cela valait quand même la peine de le dire. Le site move() est une astuce que j'utilise parfois pour des raisons de commodité, mais est-ce que C++ garantit réellement que tout ce qui sera optimisé par l'utilisation de .insert() ou est-ce que c'est juste quelque chose que les implémenteurs de bibliothèques peuvent faire s'ils sont intelligents ? J'ai supposé que c'était le cas.

3voto

Alexander Gessler Points 26717

Il y a une surcharge string operator+ (char lhs, const string& rhs); donc vous pouvez simplement faire your_string 'a' + your_string pour imiter push_front .

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

1 votes

Vous devez no utiliser std::string::resize pour "rassembler plus d'espace", la fonction agrandira le tampon interne si nécessaire, c'est vrai. Mais elle remplira également la chaîne de caractères actuelle avec char() (également connu sous le nom de NULL (c'est-à-dire la valeur 0). Voir ce qui suit pâte à code pour une démonstration.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X