Ich kenne ein wenig C und jetzt schaue ich mir C ++ an. Ich bin es gewohnt, Arrays für den Umgang mit C-Strings zu chargen, aber während ich mir C ++ - Code ansehe, sehe ich Beispiele, die sowohl String-Typ- als auch char-Arrays verwenden:
#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;
}
und
#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;
}
(beide Beispiele von http://www.cplusplus.com )
Ich nehme an, dies ist eine häufig gestellte und beantwortete (offensichtliche?) Frage, aber es wäre schön, wenn mir jemand sagen könnte, was genau der Unterschied zwischen diesen beiden Möglichkeiten für den Umgang mit Zeichenfolgen in C ++ ist (Leistung, API-Integration, wie jede einzelne ist besser, ...).
Danke dir.
Antworten:
Ein char-Array ist genau das - ein Array von Zeichen:
Eine Zeichenfolge ist eine Klasse, die ein char-Array enthält, diese jedoch automatisch für Sie verwaltet. Die meisten Zeichenfolgenimplementierungen verfügen über ein integriertes Array mit 16 Zeichen (kurze Zeichenfolgen fragmentieren den Heap nicht) und verwenden den Heap für längere Zeichenfolgen.
Sie können wie folgt auf das char-Array eines Strings zugreifen:
C ++ - Zeichenfolgen können eingebettete \ 0-Zeichen enthalten, kennen ihre Länge ohne zu zählen, sind schneller als Heap-zugewiesene Zeichenarrays für kurze Texte und schützen Sie vor Pufferüberläufen. Außerdem sind sie besser lesbar und einfacher zu bedienen.
C ++ - Zeichenfolgen sind jedoch nicht (sehr) für die Verwendung über DLL-Grenzen hinweg geeignet, da dies erfordern würde, dass jeder Benutzer einer solchen DLL-Funktion sicherstellt, dass er genau denselben Compiler und dieselbe C ++ - Laufzeitimplementierung verwendet, damit er nicht riskiert, dass sich seine Zeichenfolgenklasse anders verhält.
Normalerweise gibt eine Zeichenfolgenklasse auch ihren Heapspeicher auf dem aufrufenden Heap frei, sodass sie nur dann wieder Speicher freigeben kann, wenn Sie eine gemeinsam genutzte (.dll oder .so) Version der Laufzeit verwenden.
Kurz gesagt: Verwenden Sie C ++ - Zeichenfolgen in all Ihren internen Funktionen und Methoden. Wenn Sie jemals eine DLL oder SO schreiben, verwenden Sie C-Zeichenfolgen in Ihren öffentlichen (DLL / so exponierten) Funktionen.
quelle
Arkaitz ist richtig, das
string
ist ein verwalteter Typ. Für Sie bedeutet dies, dass Sie sich niemals Gedanken darüber machen müssen, wie lang die Zeichenfolge ist, und dass Sie sich auch nicht darum kümmern müssen, den Speicher der Zeichenfolge freizugeben oder neu zuzuweisen.Andererseits hat die
char[]
Notation im obigen Fall den Zeichenpuffer auf genau 256 Zeichen beschränkt. Wenn Sie versucht haben, mehr als 256 Zeichen in diesen Puffer zu schreiben, überschreiben Sie bestenfalls anderen Speicher, den Ihr Programm "besitzt". Im schlimmsten Fall werden Sie versuchen, Speicher zu überschreiben, den Sie nicht besitzen, und Ihr Betriebssystem wird Ihr Programm sofort beenden.Endeffekt? Strings sind viel programmiererfreundlicher, Zeichen sind für den Computer viel effizienter.
quelle
Nun, der Zeichenfolgentyp ist eine vollständig verwaltete Klasse für Zeichenfolgen, während char [] immer noch das ist, was es in C war, einem Byte-Array, das eine Zeichenfolge für Sie darstellt.
In Bezug auf API und Standardbibliothek ist alles in Form von Zeichenfolgen und nicht in Form von char [] implementiert, aber es gibt immer noch viele Funktionen von libc, die char [] empfangen, sodass Sie es möglicherweise für diese verwenden müssen, abgesehen davon, dass ich es tun würde Verwenden Sie immer std :: string.
In Bezug auf die Effizienz ist ein Rohpuffer aus nicht verwaltetem Speicher für viele Dinge natürlich fast immer schneller, aber wenn Sie beispielsweise Zeichenfolgen vergleichen, hat std :: string immer die Größe, um ihn zuerst zu überprüfen, während Sie mit char [] you arbeiten müssen Zeichen für Zeichen vergleichen.
quelle
Ich persönlich sehe keinen Grund, warum man char * oder char [] verwenden möchte, außer für die Kompatibilität mit altem Code. std :: string ist nicht langsamer als die Verwendung eines c-Strings, außer dass er die Neuzuweisung für Sie übernimmt. Sie können die Größe beim Erstellen festlegen und so eine Neuzuweisung vermeiden, wenn Sie möchten. Der Indexierungsoperator ([]) bietet einen konstanten Zeitzugriff (und ist im wahrsten Sinne des Wortes genau dasselbe wie die Verwendung eines C-String-Indexers). Wenn Sie die at-Methode verwenden, erhalten Sie auch eine überprüfte Sicherheit, die Sie mit C-Strings nur erhalten, wenn Sie sie schreiben. Ihr Compiler optimiert meistens die Verwendung des Indexers im Release-Modus. Es ist leicht, mit C-Strings herumzuspielen; Dinge wie Löschen gegen Löschen [], Ausnahmesicherheit, sogar wie man einen C-String neu zuweist.
Und wenn Sie sich mit fortgeschrittenen Konzepten wie COW-Strings und Nicht-COW für MT usw. befassen müssen, benötigen Sie std :: string.
Wenn Sie sich Sorgen um Kopien machen, solange Sie Referenzen und konstante Referenzen verwenden, wo immer Sie können, haben Sie aufgrund von Kopien keinen Overhead, und es ist dasselbe, wie Sie es mit der C-Zeichenfolge tun würden.
quelle
Strings haben Hilfsfunktionen und verwalten Char-Arrays automatisch. Sie können Zeichenfolgen verketten. Für ein char-Array, das Sie in ein neues Array kopieren müssten, können Zeichenfolgen zur Laufzeit ihre Länge ändern. Ein char-Array ist schwieriger zu verwalten als eine Zeichenfolge, und bestimmte Funktionen akzeptieren möglicherweise nur eine Zeichenfolge als Eingabe, sodass Sie das Array in eine Zeichenfolge konvertieren müssen. Es ist besser, Zeichenfolgen zu verwenden. Sie wurden so erstellt, dass Sie keine Arrays verwenden müssen. Wenn Arrays objektiv besser wären, hätten wir keine Strings.
quelle
Stellen Sie sich (char *) als string.begin () vor. Der wesentliche Unterschied besteht darin, dass (char *) ein Iterator und std :: string ein Container ist. Wenn Sie sich an grundlegende Zeichenfolgen halten, gibt Ihnen ein (char *) an, was std :: string :: iterator tut. Sie können (char *) verwenden, wenn Sie den Vorteil eines Iterators und auch die Kompatibilität mit C wünschen, aber das ist die Ausnahme und nicht die Regel. Achten Sie wie immer auf die Ungültigmachung des Iterators. Wenn Leute sagen (char *) ist nicht sicher, meinen sie das auch. Es ist so sicher wie jeder andere C ++ - Iterator.
quelle
Einer der Unterschiede ist die Nullterminierung (\ 0).
In C und C ++ nimmt char * oder char [] einen Zeiger auf ein einzelnes Zeichen als Parameter und verfolgt den Speicher, bis ein Speicherwert von 0 erreicht ist (häufig als Nullterminator bezeichnet).
C ++ - Zeichenfolgen können eingebettete \ 0-Zeichen enthalten und deren Länge kennen, ohne zu zählen.
Ausgabe:
quelle