Wann sollte ich verwenden std::string
und wann sollte ich char*
Arrays von char
s in C ++ verwalten?
Es scheint, dass Sie verwenden sollten, char*
wenn Leistung (Geschwindigkeit) entscheidend ist und Sie aufgrund der Speicherverwaltung bereit sind, ein riskantes Geschäft zu akzeptieren.
Gibt es andere zu berücksichtigende Szenarien?
char *
hat fast keinen Overhead. Was genau der Overheadstd::string
ist, weiß ich nicht, es ist wahrscheinlich implementierungsabhängig. Ich erwarte kaum, dass der Overhead viel größer ist als der eines bloßen Zeichenzeigers. Da ich keine Kopie des Standards besitze, kann ich keine Garantien des Standards detailliert beschreiben. Jeder Leistungsunterschied hängt wahrscheinlich von den auszuführenden Vorgängen ab.std::string::size
könnte die Größe neben den Zeichendaten speichern und somit schneller sein alsstrlen
.append(const string&)
undappend(const char*, size_t)
anstelle vonoperator+=()
.Mein Standpunkt ist:
quelle
Verwendung von Rohzeichenfolgen
Ja, manchmal kann man das wirklich. Wenn Sie const char *, char-Arrays, die auf dem Stack zugewiesen sind, und String-Literale verwenden, können Sie dies so tun, dass überhaupt keine Speicherzuweisung erfolgt.
Das Schreiben eines solchen Codes erfordert oft mehr Nachdenken und Sorgfalt als die Verwendung von Zeichenfolgen oder Vektoren, kann jedoch mit geeigneten Techniken durchgeführt werden. Mit den richtigen Techniken kann der Code sicher sein, aber Sie müssen immer sicherstellen, dass Sie beim Kopieren in char [] entweder einige Garantien für die Länge der zu kopierenden Zeichenfolge haben oder dass Sie übergroße Zeichenfolgen ordnungsgemäß prüfen und handhaben. Wenn Sie dies nicht tun, hat die strcpy-Funktionsfamilie den Ruf, unsicher zu sein.
Wie Vorlagen beim Schreiben sicherer Zeichenpuffer helfen können
In Bezug auf die Sicherheit von char [] -Puffern können Vorlagen hilfreich sein, da sie eine Kapselung für die Behandlung der Puffergröße für Sie erstellen können. Vorlagen wie diese werden z. B. von Microsoft implementiert, um strcpy sicher zu ersetzen. Das Beispiel hier ist aus meinem eigenen Code extrahiert, der echte Code hat viel mehr Methoden, aber dies sollte ausreichen, um die Grundidee zu vermitteln:
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; }
quelle
char*
Zeichenfolgen sind nicht immer auf dem Stapel.char *str = (char*)malloc(1024); str[1024] = 0;
Eine Gelegenheit, die Sie verwenden MÜSSEN
char*
und nicht,std::string
ist, wenn Sie statische Zeichenfolgenkonstanten benötigen. Der Grund dafür ist, dass Sie keine Kontrolle über die Reihenfolge haben, in der Module ihre statischen Variablen initialisieren, und ein anderes globales Objekt aus einem anderen Modul möglicherweise auf Ihre Zeichenfolge verweist, bevor es initialisiert wird. http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Static_and_Global_Variablesstd::string
Profis:std::string
Nachteile: - Zwei unterschiedliche STL-Zeichenfolgeninstanzen können nicht denselben zugrunde liegenden Puffer gemeinsam nutzen. Wenn Sie also den Wert übergeben, erhalten Sie immer eine neue Kopie. - Es gibt einige Leistungseinbußen, aber ich würde sagen, wenn Ihre Anforderungen nicht besonders sind, ist dies vernachlässigbar.quelle
Sie sollten die Verwendung
char*
in folgenden Fällen in Betracht ziehen :Tatsächlich werden sie in C ++
char*
häufig für feste kleine Wörter wie Optionen, Dateinamen usw. verwendet.quelle
Wann wird ein c ++ std :: string verwendet?
Wann wird char * verwendet?
quelle
Verwenden Sie (const) char * als Parameter, wenn Sie eine Bibliothek schreiben. std :: string-Implementierungen unterscheiden sich zwischen verschiedenen Compilern.
quelle
Wenn Sie C-Bibliotheken verwenden möchten, müssen Sie sich mit C-Strings befassen. Gleiches gilt, wenn Sie Ihre API C aussetzen möchten.
quelle
Sie können davon ausgehen, dass die meisten Operationen an einem std :: string (z. B. z. B.
find
) so optimiert wie möglich sind, sodass sie wahrscheinlich mindestens so gut wie ein reines C-Gegenstück funktionieren .Es ist auch erwähnenswert, dass std :: string-Iteratoren häufig Zeigern in das zugrunde liegende char-Array zugeordnet werden. Daher ist jeder Algorithmus, den Sie über Iteratoren entwickeln, in Bezug auf die Leistung im Wesentlichen identisch mit demselben Algorithmus über char *.
Beachten Sie beispielsweise
operator[]
Folgendes: Die meisten STL-Implementierungen führen keine Grenzwertprüfung durch und sollten dies in dieselbe Operation für das zugrunde liegende Zeichenarray übersetzen. AFAIK STLPort kann optional eine Grenzwertprüfung durchführen. Zu diesem Zeitpunkt wäre dieser Operator etwas langsamer.Was bringt Ihnen die Verwendung von std :: string? Es befreit Sie von der manuellen Speicherverwaltung. Das Ändern der Größe des Arrays wird einfacher, und Sie müssen im Allgemeinen weniger über die Freigabe von Speicher nachdenken.
Wenn Sie sich beim Ändern der Größe eines Strings Sorgen um die Leistung machen, gibt es eine
reserve
Funktion, die Sie möglicherweise nützlich finden.quelle
Wenn Sie das Zeichenarray in ähnlichem Text usw. verwenden, verwenden Sie std :: string flexibler und benutzerfreundlicher. Wenn Sie es für etwas anderes wie Datenspeicherung verwenden? Arrays verwenden (Vektoren bevorzugen)
quelle
Auch wenn die Leistung entscheidend ist, sollten Sie sie besser nutzen
vector<char>
- sie ermöglicht die Speicherzuweisung im Voraus (Reserve () -Methode) und hilft Ihnen, Speicherlecks zu vermeiden. Die Verwendung von vector :: operator [] führt zu einem Overhead, aber Sie können die Adresse des Puffers jederzeit extrahieren und genau so indizieren, als wäre es ein Zeichen *.quelle
AFAIK implementiert intern die meisten std :: string-Kopien beim Schreiben, referenzgezählte Semantik, um Overhead zu vermeiden, selbst wenn Strings nicht als Referenz übergeben werden.
quelle