Question

Existe-t-il une bonne raison d'utiliser les chaînes de caractères C en C ++? Mon manuel les utilise dans des exemples à certains moments, et j’ai vraiment l’impression que ce serait plus simple d’utiliser un std :: string.

Était-ce utile?

La solution

La seule raison pour laquelle je les ai utilisées, c’est lors de l’interfaçage avec des bibliothèques tierces utilisant des chaînes de style C. Il peut également y avoir des situations ésotériques dans lesquelles vous utiliseriez des chaînes de style C pour des raisons de performances, mais le plus souvent, l’utilisation de méthodes sur des chaînes C ++ est probablement plus rapide en raison de l’insertion et de la spécialisation, etc.

Vous pouvez utiliser la méthode c_str() dans de nombreux cas. lorsque vous travaillez avec ce type d’API, sachez que char * renvoyé est const et que vous ne devez pas modifier la chaîne via ce pointeur. Dans ce genre de situation, vous pouvez toujours utiliser un vecteur & Lt; char & Gt; au lieu de cela, et bénéficiez au moins d’une gestion plus simple de la mémoire.

Autres conseils

Quelques notes supplémentaires sur le contrôle de la mémoire:

Les chaînes C sont des types de POD, elles peuvent donc être affectées dans le segment de données en lecture seule de votre application. Si vous déclarez et définissez std::string des constantes au niveau de l'espace de noms, le compilateur générera du code supplémentaire qui s'exécutera avant main() et qui appelle le constructeur <=> pour chaque constante. Si votre application comporte de nombreuses chaînes constantes (par exemple, si vous avez généré du code C ++ utilisant des chaînes constantes), les chaînes C peuvent être préférables dans cette situation.

Certaines implémentations de <=> prennent en charge une fonctionnalité appelée SSO (& "optimisation de chaîne courte &" ou & "optimisation de petite chaîne &";) où la classe <=> contient stockage pour les chaînes d'une certaine longueur. Cela augmente la taille de <=> mais réduit souvent de manière significative la fréquence des allocations / désallocations de librairies, améliorant ainsi les performances. Si votre implémentation de <=> ne prend pas en charge l'authentification unique, la construction d'un <=> vide sur la pile effectuera toujours une allocation de magasin gratuit. Si tel est le cas, l'utilisation de chaînes C temporaires allouées à la pile peut s'avérer utile pour le code essentiel à la performance qui utilise des chaînes. Bien sûr, vous devez faire attention à ne pas vous tirer une balle dans le pied lorsque vous faites cela.

Parce que c'est comme ça qu'ils viennent de nombreuses API / bibliothèques?

Supposons que votre code comporte des constantes de chaîne, ce qui est un besoin assez courant. Il est préférable de les définir en tant que chaînes C plutôt qu'en tant qu'objets C ++ - plus légers, plus portables, etc. Maintenant, si vous allez passer ces chaînes à diverses fonctions, il est utile que ces fonctions acceptent une chaîne C au lieu de nécessiter une Objet chaîne C ++.

Bien sûr, si les chaînes sont mutables, il est beaucoup plus pratique d’utiliser des objets chaîne C ++.

Contrôle de la mémoire. J'ai récemment eu à manipuler des chaînes (en réalité des blobs d'une base de données) d'environ 200 à 300 Mo, dans une application massivement multithread. C'était une situation où juste une copie supplémentaire de la chaîne pouvait avoir éclaté l'espace d'adressage 32 bits. Je devais savoir exactement combien de copies de la chaîne existaient. Bien que je sois un évangéliste du TSL, j’ai utilisé char * à ce moment-là, car cela me garantissait qu’aucune mémoire supplémentaire ni même aucune copie supplémentaire n’était allouée. Je savais exactement de combien d'espace il aurait besoin.

En dehors de cela, le traitement standard des chaînes STL omet certaines fonctions C intéressantes pour le traitement / l'analyse des chaînes. Heureusement, std :: string a la méthode c_str () pour un accès constant au tampon interne. Pour utiliser printf (), vous devez quand même utiliser char * (quelle idée folle de l'équipe C ++ de ne pas inclure les fonctionnalités de type printf, l'une des fonctions les plus utiles de tous les temps en C. J'espère que boost :: format bientôt être inclus dans la STL.

Si une fonction nécessite une chaîne constante , je préfère néanmoins utiliser 'const char *' (ou const wchar_t *) même si le programme utilise std :: string, CString, EString ou autre.

Il y a trop de sources de chaînes dans une base de code volumineuse pour être sûr que l'appelant aura la chaîne sous la forme d'un std :: string et que "const char *" est le plus petit dénominateur commun.

Les manuels contiennent des chaînes C old-school car de nombreuses fonctions de base les attendent toujours comme arguments ou les renvoient. De plus, il donne un aperçu de la structure sous-jacente de la chaîne en mémoire.

Si le code C ++ est & "; profond &"; (près du noyau, fortement dépendant des bibliothèques C, etc.) vous pouvez utiliser explicitement les chaînes C pour éviter de nombreuses conversions dans et hors de std :: string. Bien entendu, si vous vous connectez avec d'autres domaines linguistiques (Python, Ruby, etc.), vous pouvez le faire pour la même raison. Sinon, utilisez std :: string.

Certains messages font état de problèmes de mémoire. C'est peut-être une bonne raison pour éviter std :: string, mais char * n'est probablement pas le meilleur remplaçant. C'est toujours un langage OO. Votre propre classe de chaîne est probablement meilleure qu’un char *. Cela peut même être plus efficace - vous pouvez appliquer l'optimisation des petites chaînes, par exemple.

Dans mon cas, j’essayais de récupérer environ 1 Go de chaînes dans un fichier de 2 Go, de les insérer dans des enregistrements contenant environ 60 champs, puis de les trier 7 fois sur différents champs. Le code de mon prédécesseur prenait 25 heures avec char * et mon code s’exécutait en 1 heure.

Après avoir passé beaucoup, beaucoup trop de temps à déboguer les règles d'initialisation et chaque implémentation de chaîne imaginable sur plusieurs plates-formes, nous demandons que les chaînes statiques soient const char *.

Après avoir passé beaucoup, beaucoup trop de temps à déboguer des codes de type char * et des fuites de mémoire, je suggère que toutes les chaînes non statiques soient un type d’objet chaîne ... jusqu’à ce que le profil montre que vous pouvez et devez faire mieux; - )

Étant donné le choix, il n'y a généralement aucune raison de choisir des chaînes C primitives (char*) plutôt que des chaînes C ++ (std::string). Cependant, vous n'avez souvent pas le luxe du choix. Par exemple, les constructeurs de std::fstream prennent les chaînes C, pour des raisons historiques. De plus, les bibliothèques C (vous l’avez deviné!) Utilisent des chaînes C.

Dans votre propre code C ++, il est préférable d'utiliser c_str() et d'extraire la chaîne C de l'objet à l'aide du <=> fonction de <=> .

Cela dépend des bibliothèques que vous utilisez. Par exemple, lorsque vous travaillez avec le MFC , il est souvent plus facile d'utiliser CString lorsque vous travaillez avec différentes parties. de l'API Windows. Il semble également que sa performance soit supérieure à celle de std :: string dans les applications Win32.

Cependant, std :: string fait partie de la norme C ++, donc si vous voulez une meilleure portabilité, utilisez std :: string.

Pour les applications telles que la plupart des plates-formes intégrées où vous n'avez pas le luxe d'un tas de stocker les chaînes à manipuler et où une pré-affectation déterministe des mémoires tampons est requise.

Les chaînes c ne supportent pas la surcharge d'être une classe.

Les chaînes c peuvent généralement générer un code plus rapide, car elles sont plus proches du niveau de la machine

Cela ne veut pas dire que vous ne pouvez pas écrire de mauvais code avec eux. Ils peuvent être mal utilisés, comme toute autre construction.

Il existe une multitude d'appels à la librairie qui les exigent pour des raisons historiques.

Apprenez à utiliser les chaînes c et stl et à utiliser chacune d'elles lorsqu'il est logique de le faire.

1) & "constante de chaîne &"; est une chaîne C (const char *), la convertissant en const std :: string & amp; est un processus d'exécution, pas nécessairement simple ou optimisé. 2) La bibliothèque fstream utilise des chaînes de style c pour transmettre les noms de fichiers.

Ma règle d'or est de passer const std :: string & amp; si je suis sur le point d'utiliser les données comme std :: string de toute façon (par exemple, quand je les stocke dans un vecteur), et const char * dans les autres cas.

Code hérité qui ne connaît pas std :: string. De plus, avant C ++ 11, l’ouverture de fichiers avec std :: ifstream ou std :: ofstream n’était possible qu’avec const char * comme entrée du nom de fichier.

Les chaînes STL sont certainement beaucoup plus simples à utiliser et je ne vois aucune raison de ne pas les utiliser.

Si vous avez besoin d'interagir avec une bibliothèque qui n'utilise que des chaînes de style C comme arguments, vous pouvez toujours appeler la méthode c_str () de la classe string.

La raison habituelle est que vous aimez écrire des dépassements de mémoire tampon lors de la gestion de votre chaîne. Les chaînes comptées sont si supérieures aux chaînes terminées qu'il est difficile de comprendre pourquoi les concepteurs C ont déjà utilisé des chaînes terminées. C'était une mauvaise décision alors; c'est une mauvaise décision maintenant.

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