Question

Quand devrais-je utiliser std::string et quand devrais-je utiliser char* pour gérer des tableaux de char s en C ++?

Il semble que vous devriez utiliser <=> si les performances (rapidité) sont essentielles et si vous êtes prêt à accepter certaines activités risquées en raison de la gestion de la mémoire.

Existe-t-il d'autres scénarios à considérer?

Était-ce utile?

La solution

Vous pouvez passer std :: strings par référence s'ils sont volumineux pour éviter la copie ou un pointeur sur l'occurrence, je ne vois donc aucun avantage réel à utiliser les pointeurs de caractère.

J'utilise std :: string / wstring pour plus ou moins tout le texte réel. char * est utile pour d’autres types de données et vous pouvez être sûr qu’elles seront désallouées comme il se doit. Sinon std :: vector est le chemin à parcourir.

Il y a probablement des exceptions à tout cela.

Autres conseils

Mon point de vue est le suivant:

  • N'utilisez jamais char * si vous n'appelez pas " C " code.
  • Utilisez toujours std :: string: c'est plus facile, c'est plus convivial, c'est optimisé, c'est standard, cela vous évitera d'avoir des bugs, cela a été vérifié et prouvé.

Utilisation de la chaîne brute

Oui, parfois, vous pouvez vraiment faire cela. Lorsque vous utilisez const char *, les tableaux de caractères alloués sur la pile et les littéraux de chaîne, vous pouvez le faire de manière à ce qu'il n'y ait aucune allocation de mémoire.

L'écriture d'un tel code nécessite souvent plus de réflexion et de soin que l'utilisation de chaînes ou de vecteurs, mais avec des techniques appropriées, cela peut être fait. Avec des techniques appropriées, le code peut être sécurisé, mais vous devez toujours vous assurer que, lors de la copie dans char [], vous avez des garanties sur la longueur de la chaîne copiée ou que vous vérifiez et gérez les chaînes surdimensionnées avec élégance. Ne pas le faire est ce qui a donné à la famille de fonctions strcpy la réputation d’être dangereux.

Comment les modèles peuvent aider à écrire des tampons de caractères sécurisés

En ce qui concerne la sécurité des tampons char [], les modèles peuvent vous aider, car ils peuvent créer une encapsulation pour gérer la taille de la mémoire tampon pour vous. De tels modèles sont implémentés, par exemple par Microsoft pour fournir des remplacements sûrs pour strcpy. L'exemple ici est extrait de mon propre code, le code réel a beaucoup plus de méthodes, mais cela devrait suffire à transmettre l'idée de base:

template <int Size>
class BString
{
  char _data[Size];

  public:
  BString()
  {
    _data[0]=0;
    // note: last character will always stay zero
    // if not, overflow occurred
    // all constructors should contain last element initialization
    // so that it can be verified during destruction
    _data[Size-1]=0;
  }
  const BString &operator = (const char *src)
  {
    strncpy(_data,src,Size-1);
    return *this;
  }

  operator const char *() const {return _data;}
};

//! overloads that make conversion of C code easier 
template <int Size>
inline const BString<Size> & strcpy(BString<Size> &dst, const char *src)
{
  return dst = src;
}

Vous devez obligatoirement utiliser char* et non std::string lorsque vous avez besoin de constantes de chaîne statiques. La raison en est que vous n’avez aucun contrôle sur les modules d’ordre qui initialisent leurs variables statiques, et un autre objet global d’un module différent peut faire référence à votre chaîne avant son initialisation. http://google-styleguide.googlecode.com/svn/trunk/ cppguide.xml # Static_and_Global_Variables

<=> pros:

  • gère la mémoire pour vous (la chaîne peut croître et l'implémentation vous allouera un tampon plus grand)
  • Interface de programmation de niveau supérieur, fonctionne bien avec le reste de STL.

<=> contre: - deux instances de chaîne STL distinctes ne peuvent pas partager le même tampon sous-jacent. Donc, si vous passez par valeur, vous obtenez toujours une nouvelle copie. - Il y a une pénalité de performance, mais je dirais que si vos exigences ne sont pas spéciales, c'est négligeable.

Vous devriez envisager d'utiliser char* dans les cas suivants:

  • Ce tableau sera passé en paramètre.
  • Vous connaissez d'avance la taille maximale de votre tableau (vous le savez ou vous l'imposez).
  • Vous ne ferez aucune transformation sur ce tableau.

En fait, en C ++, <=> sont souvent utilisés pour les petits mots fixes, comme options, nom de fichier, etc ...

Quand utiliser un c ++ std :: string:

    Les
  • chaînes sont globalement plus sécurisées que char *. Normalement, lorsque vous utilisez char *, vous devez vérifier les choses pour vous assurer que tout va bien. Dans la classe string, tout est fait pour vous.
  • Habituellement, lorsque vous utilisez char *, vous devez libérer la mémoire que vous avez allouée. Vous n'avez pas à le faire avec une chaîne, car elle libère son tampon interne lors de la destruction.
  • Les chaînes fonctionnent bien avec c ++ stringstream, les entrées / sorties formatées sont très simples.

Quand utiliser char *

  • Utiliser char * vous donne plus de contrôle sur ce qui se passe & "derrière &"; les scènes, ce qui signifie que vous pouvez ajuster la performance si vous en avez besoin.

Utilisez char (const) * comme paramètres si vous écrivez une bibliothèque. Les implémentations de std :: string diffèrent d'un compilateur à l'autre.

Si vous souhaitez utiliser les bibliothèques C, vous devrez gérer des chaînes de caractères. Il en va de même si vous souhaitez exposer votre API à C.

Vous pouvez vous attendre à ce que la plupart des opérations sur un std :: string (tel que, par exemple, find) soient aussi optimisées que possible, de sorte qu'elles fonctionnent au moins aussi bien que leur équivalent C pur.

Il convient également de noter que les itérateurs std :: string mappent assez souvent des pointeurs dans le tableau de caractères sous-jacent. Ainsi, tout algorithme que vous concevez au-dessus des itérateurs est essentiellement identique au même algorithme au-dessus de char * en termes de performances.

Les choses à surveiller sont, par exemple, operator[] - la plupart des implémentations STL n'effectuent pas de vérification des limites et doivent les traduire en une même opération sur le tableau de caractères sous-jacent. AFAIK STLPort peut éventuellement effectuer une vérification des limites, auquel cas cet opérateur serait un peu plus lent.

Alors, que gagne std :: string? Cela vous dispense de la gestion manuelle de la mémoire; le redimensionnement de la matrice devient plus facile et vous devez généralement moins réfléchir à la libération de mémoire.

Si vous êtes préoccupé par les performances lors du redimensionnement d'une chaîne, une reserve fonction peut vous être utile.

si vous utilisez le tableau de caractères dans du texte, etc., utilisez std :: string plus souple et plus facile à utiliser. Si vous l'utilisez pour autre chose que le stockage de données? utilisez des tableaux (préférez les vecteurs)

Même lorsque les performances sont cruciales, il vaut mieux utiliser vector<char> - cela permet d'allouer la mémoire à l'avance (méthode reserve ()) et vous aidera à éviter les fuites de mémoire. L'utilisation de vector :: operator [] entraîne une surcharge, mais vous pouvez toujours extraire l'adresse du tampon et l'indexer exactement comme s'il s'agissait d'un caractère *.

AFAIK en interne, la plupart des std :: string implémentent la copie lors de l'écriture, la sémantique comptée des références évitant les pertes de temps, même si les chaînes ne sont pas transmises par référence.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top