Je connais un peu C et maintenant je regarde C ++. Je suis habitué aux tableaux de caractères pour traiter les chaînes C, mais pendant que je regarde le code C ++, je vois qu'il y a des exemples utilisant à la fois le type de chaîne et les tableaux de caractères:
#include <iostream>
#include <string>
using namespace std;
int main () {
string mystr;
cout << "What's your name? ";
getline (cin, mystr);
cout << "Hello " << mystr << ".\n";
cout << "What is your favorite team? ";
getline (cin, mystr);
cout << "I like " << mystr << " too!\n";
return 0;
}
et
#include <iostream>
using namespace std;
int main () {
char name[256], title[256];
cout << "Enter your name: ";
cin.getline (name,256);
cout << "Enter your favourite movie: ";
cin.getline (title,256);
cout << name << "'s favourite movie is " << title;
return 0;
}
(deux exemples de http://www.cplusplus.com )
Je suppose que c'est une question largement posée et répondue (évidente?), Mais ce serait bien si quelqu'un pouvait me dire quelle est exactement la différence entre ces deux façons de traiter les chaînes en C ++ (performances, intégration d'API, la façon dont chacune est meilleur, ...).
Je vous remercie.
Réponses:
Un tableau de caractères est juste cela - un tableau de caractères:
Une chaîne est une classe qui contient un tableau de caractères, mais qui le gère automatiquement pour vous. La plupart des implémentations de chaînes ont un tableau intégré de 16 caractères (les chaînes courtes ne fragmentent donc pas le tas) et utilisent le tas pour les chaînes plus longues.
Vous pouvez accéder au tableau de caractères d'une chaîne comme ceci:
Les chaînes C ++ peuvent contenir des caractères \ 0 incorporés, connaître leur longueur sans compter, sont plus rapides que les tableaux de caractères alloués par tas pour les textes courts et vous protègent des dépassements de tampon. De plus, ils sont plus lisibles et plus faciles à utiliser.
Cependant, les chaînes C ++ ne conviennent pas (très) à une utilisation à travers les limites de la DLL, car cela exigerait que tout utilisateur d'une telle fonction DLL s'assure qu'il utilise exactement le même compilateur et la même implémentation d'exécution C ++, de peur qu'il ne risque que sa classe de chaînes se comporte différemment.
Normalement, une classe de chaîne libère également sa mémoire de tas sur le tas appelant, donc elle ne pourra à nouveau libérer de la mémoire que si vous utilisez une version partagée (.dll ou .so) du runtime.
En bref: utilisez des chaînes C ++ dans toutes vos fonctions et méthodes internes. Si jamais vous écrivez un .dll ou .so, utilisez des chaînes C dans vos fonctions publiques (dll / ainsi exposées).
la source
Arkaitz a raison de dire qu'il
string
s'agit d'un type géré. Cela signifie pour vous que vous n'avez jamais à vous soucier de la longueur de la chaîne, ni à vous soucier de la libération ou de la réallocation de la mémoire de la chaîne.D'autre part, la
char[]
notation dans le cas ci-dessus a limité le tampon de caractères à exactement 256 caractères. Si vous essayez d'écrire plus de 256 caractères dans ce tampon, au mieux vous écraserez une autre mémoire que votre programme "possède". Au pire, vous essaierez d'écraser la mémoire que vous ne possédez pas, et votre système d'exploitation tuera votre programme sur place.En bout de ligne? Les chaînes sont beaucoup plus conviviales pour les programmeurs, les char [] sont beaucoup plus efficaces pour l'ordinateur.
la source
Eh bien, le type de chaîne est une classe entièrement gérée pour les chaînes de caractères, tandis que char [] est toujours ce qu'il était en C, un tableau d'octets représentant une chaîne de caractères pour vous.
En termes d'API et de bibliothèque standard, tout est implémenté en termes de chaînes et non de char [], mais il y a encore beaucoup de fonctions de la libc qui reçoivent char [] donc vous devrez peut-être l'utiliser pour celles-ci, à part cela, je voudrais utilisez toujours std :: string.
En termes d'efficacité bien sûr, un tampon brut de mémoire non gérée sera presque toujours plus rapide pour beaucoup de choses, mais prenez en compte la comparaison des chaînes par exemple, std :: string a toujours la taille pour le vérifier en premier, tandis qu'avec char [] vous besoin de comparer caractère par caractère.
la source
Personnellement, je ne vois aucune raison pour laquelle on aimerait utiliser char * ou char [] sauf pour la compatibilité avec l'ancien code. std :: string n'est pas plus lent que d'utiliser une chaîne en C, sauf qu'il gérera la réallocation pour vous. Vous pouvez définir sa taille lors de sa création, et ainsi éviter la réallocation si vous le souhaitez. Son opérateur d'indexation ([]) fournit un accès en temps constant (et dans tous les sens du mot, c'est exactement la même chose que l'utilisation d'un indexeur de chaînes en C). L'utilisation de la méthode at vous donne également la sécurité des limites vérifiées, ce que vous n'obtenez pas avec les chaînes C, à moins que vous ne l'écriviez. Votre compilateur optimisera le plus souvent l'utilisation de l'indexeur en mode version. Il est facile de jouer avec les chaînes C; des choses telles que delete vs delete [], la sécurité des exceptions, même comment réallouer une chaîne de caractères.
Et lorsque vous devez gérer des concepts avancés comme avoir des chaînes COW, et non-COW pour MT, etc., vous aurez besoin de std :: string.
Si vous vous inquiétez des copies, tant que vous utilisez des références et des références const partout où vous le pouvez, vous n'aurez pas de surcharge due aux copies, et c'est la même chose que vous feriez avec la chaîne c.
la source
Les chaînes ont des fonctions d'assistance et gèrent automatiquement les tableaux de caractères. Vous pouvez concaténer des chaînes, pour un tableau de caractères, vous devez le copier dans un nouveau tableau, les chaînes peuvent changer leur longueur au moment de l'exécution. Un tableau de caractères est plus difficile à gérer qu'une chaîne et certaines fonctions peuvent n'accepter qu'une chaîne en entrée, ce qui vous oblige à convertir le tableau en chaîne. Il est préférable d'utiliser des chaînes, elles ont été conçues pour que vous n'ayez pas à utiliser de tableaux. Si les tableaux étaient objectivement meilleurs, nous n'aurions pas de chaînes.
la source
Pensez à (char *) comme string.begin (). La différence essentielle est que (char *) est un itérateur et std :: string est un conteneur. Si vous vous en tenez aux chaînes de base, un (char *) vous donnera ce que fait std :: string :: iterator. Vous pouvez utiliser (char *) lorsque vous souhaitez bénéficier d'un itérateur et également de la compatibilité avec C, mais c'est l'exception et non la règle. Comme toujours, faites attention à l'invalidation de l'itérateur. Quand les gens disent que (char *) n'est pas sûr, c'est ce qu'ils veulent dire. Il est aussi sûr que tout autre itérateur C ++.
la source
L'une des différences est la terminaison Null (\ 0).
En C et C ++, char * ou char [] prendra un pointeur vers un seul caractère comme paramètre et suivra le long de la mémoire jusqu'à ce qu'une valeur de mémoire 0 soit atteinte (souvent appelée le terminateur nul).
Les chaînes C ++ peuvent contenir des caractères \ 0 incorporés, connaître leur longueur sans compter.
Production:
la source