it-swarm.com.de

Unterschied zwischen den Typen string und char [] in C++

Ich weiß ein wenig C und jetzt schaue ich mir C++ an. Ich bin es gewohnt, Arrays für den Umgang mit C-Strings zu verwenden, aber während ich C++ - Code anschaue, sehe ich, dass es Beispiele gibt, die sowohl den String-Typ als auch den Char-Code verwenden Arrays:

#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 aus 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 ist, mit Strings in C++ umzugehen (Leistung, API-Integration, wie jede einzelne ist) besser, ...).

Vielen Dank.

108
ramosg

Ein Char-Array ist genau das - ein Array von Zeichen:

  • Wenn auf dem Stapel (wie in Ihrem Beispiel) zugewiesen, wird es z. B. immer belegt. 256 Bytes, egal wie lang der enthaltene Text ist
  • Wenn Sie auf dem Heap (mit malloc () oder new char []) zugewiesen werden, sind Sie dafür verantwortlich, den Speicher anschließend freizugeben, und Sie haben immer den Overhead einer Heap-Zuweisung. 
  • Wenn Sie einen Text mit mehr als 256 Zeichen in das Array kopieren, kann dies zum Absturz führen, hässliche Bestätigungsmeldungen erzeugen oder an anderer Stelle in Ihrem Programm unerklärliches (Fehl-) Verhalten verursachen.
  • Um die Länge des Textes zu bestimmen, muss das Array zeichenweise nach einem\0-Zeichen durchsucht werden.

Eine Zeichenfolge ist eine Klasse, die ein Char-Array enthält, das jedoch automatisch für Sie verwaltet wird. Die meisten Zeichenfolgenimplementierungen verfügen über ein integriertes Array von 16 Zeichen (dh, kurze Zeichenfolgen fragmentieren den Heap nicht) und verwenden den Heap für längere Zeichenfolgen.

Sie können folgendermaßen auf ein Zeichenarray eines Strings zugreifen:

std::string myString = "Hello World";
const char *myStringChars = myString.c_str();

C++ - Zeichenfolgen können eingebettete\0-Zeichen enthalten, wissen deren Länge ohne zu zählen, sind schneller als von Heap zugewiesene Char-Arrays für kurze Texte und schützen Sie vor Pufferüberläufen. Außerdem sind sie lesbarer und benutzerfreundlicher.

-

C++ - Zeichenfolgen sind jedoch nicht (sehr) für die Verwendung über DLL - Grenzen hinweg geeignet, da dazu ein Benutzer einer solchen DLL - Funktion erforderlich wäre, um sicherzustellen, dass er exakt denselben Compiler und die gleiche C++ - Laufzeitimplementierung verwendet er riskiert, dass sich seine Saitenklasse anders verhält.

Normalerweise gibt eine String-Klasse auch den Heapspeicher auf dem aufrufenden Heapspeicher frei. Sie kann also nur wieder Speicherplatz freigeben, wenn Sie eine gemeinsam genutzte Version (.dll oder .so) der Laufzeitumgebung verwenden.

Kurz gesagt: Verwenden Sie C++ - Strings in allen Ihren internen Funktionen und Methoden. Wenn Sie jemals eine .dll oder .so schreiben, verwenden Sie C-Strings in Ihren öffentlichen (dll/so exponierten) Funktionen.

159
Cygon

Arkaitz ist richtig, dass string ein verwalteter Typ ist. Für Sie bedeutet dies, dass Sie sich nie Sorgen darüber machen müssen, wie lang die Zeichenfolge ist, und Sie müssen sich auch keine Gedanken darüber machen, ob der Speicher der Zeichenfolge freigegeben oder neu zugewiesen wird.

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, werden Sie bestenfalls den anderen Speicher überschreiben, 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? Zeichenketten sind viel programmierfreundlicher, Zeichen sind für den Computer viel effizienter.

10
Mark Rushakoff

Der Zeichenfolgentyp ist eine vollständig verwaltete Klasse für Zeichenfolgen, während char [] immer noch das ist, was es in C war, ein Byte-Array, das eine Zeichenfolge für Sie darstellt.

In Bezug auf API und Standardbibliothek wird alles in Form von Strings und nicht von char [] implementiert, aber es gibt immer noch viele Funktionen aus der libc, die char [] erhalten, sodass Sie sie möglicherweise für diese verwenden müssen, abgesehen davon würde ich dies tun Verwenden Sie immer std :: string.

In Bezug auf die Effizienz ist ein Rohpuffer für nicht verwalteten Speicher natürlich für viele Dinge fast immer schneller. Berücksichtigen Sie jedoch den Vergleich von Zeichenfolgen, z. B. hat std :: string die Größe, um es zuerst zu überprüfen, während Sie mit char [] you arbeiten müssen Zeichen für Zeichen vergleichen.

6
Arkaitz Jimenez

Ich persönlich sehe keinen Grund, warum man char * oder char [] verwenden möchte, außer zur Kompatibilität mit altem Code. std :: string ist nicht langsamer als die Verwendung eines c-Strings, außer dass die Neuzuweisung für Sie erledigt wird. Sie können die Größe beim Erstellen festlegen und somit eine Neuzuordnung vermeiden, wenn Sie möchten. Sein Indexierungsoperator ([]) bietet einen konstanten Zeitzugriff (und ist in jeder Hinsicht genau das gleiche wie ein C-String-Indexer). Wenn Sie die at-Methode verwenden, erhalten Sie auch eine begrenzte Sicherheit, die Sie mit c-Strings nicht erhalten, wenn Sie sie nicht schreiben. Ihr Compiler optimiert meistens die Verwendung des Indexers im Freigabemodus. Es ist leicht, mit C-Strings herumzuspielen; Dinge wie delete vs delete [], Ausnahmesicherheit, sogar wie eine C-Zeichenfolge neu zugewiesen wird.

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 Verweise verwenden, und Verweise auf const, wo immer Sie können, entstehen keine zusätzlichen Kosten aufgrund von Kopien.

5
Abhay

Strings haben Hilfsfunktionen und verwalten Char-Arrays automatisch. Sie können Strings verketten. Für ein Char-Array müssten Sie es in ein neues Array kopieren. Strings können ihre Länge zur Laufzeit ändern. Ein Char-Array ist schwieriger zu verwalten als ein String, und bestimmte Funktionen akzeptieren möglicherweise nur einen String als Eingabe, sodass Sie das Array in einen String konvertieren müssen. Es ist besser, Strings zu verwenden. Sie wurden so erstellt, dass Sie keine Arrays verwenden müssen. Wenn Arrays objektiv besser wären, hätten wir keine Strings.

1
theo2003

Einer der Unterschiede ist die Nullkündigung (\ 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 wird (häufig als Nullabschlußzeichen bezeichnet).

C++ - Zeichenfolgen können eingebettete\0-Zeichen enthalten, deren Länge ohne Zählen bekannt ist. 

#include<stdio.h>
#include<string.h>
#include<iostream>

using namespace std;

void NullTerminatedString(string str){
   int NUll_term = 3;
   str[NUll_term] = '\0';       // specific character is kept as NULL in string
   cout << str << endl <<endl <<endl;
}

void NullTerminatedChar(char *str){
   int NUll_term = 3;
   str[NUll_term] = 0;     // from specific, all the character are removed 
   cout << str << endl;
}

int main(){
  string str = "Feels Happy";
  printf("string = %s\n", str.c_str());
  printf("strlen = %d\n", strlen(str.c_str()));  
  printf("size = %d\n", str.size());  
  printf("sizeof = %d\n", sizeof(str)); // sizeof std::string class  and compiler dependent
  NullTerminatedString(str);


  char str1[12] = "Feels Happy";
  printf("char[] = %s\n", str1);
  printf("strlen = %d\n", strlen(str1));
  printf("sizeof = %d\n", sizeof(str1));    // sizeof char array
  NullTerminatedChar(str1);
  return 0;
}

Ausgabe:

strlen = 11
size = 11
sizeof = 32  
Fee s Happy


strlen = 11
sizeof = 12
Fee
0
Eswaran Pandi

Stellen Sie sich (char *) als string.begin () vor. Der wesentliche Unterschied besteht darin, dass (char *) ein Iterator ist und std :: string ein Container ist. Wenn Sie sich an grundlegende Zeichenfolgen halten, erhalten Sie mit (char *) die Funktion von std :: string :: iterator. Sie können (char *) verwenden, wenn Sie den Vorteil eines Iterators und auch die Kompatibilität mit C wünschen, dies ist jedoch die Ausnahme und nicht die Regel. Achten Sie wie immer auf die Ungültigkeit des Iterators. Wenn die Leute sagen, dass (char *) nicht sicher ist, meinen sie dies. Es ist so sicher wie jeder andere C++ - Iterator.

0