Dies ist ein alter Thread und ich denke, dass die anderen Antworten großartig sind, aber etwas übersehen, also hier sind meine (späten) 2 Cent.
Syntaktische Zuckerbeschichtung verbirgt Komplexität
Das Problem mit Strings ist, dass sie in den meisten Sprachen Bürger zweiter Klasse sind und tatsächlich die meiste Zeit nicht wirklich Teil der Sprachspezifikation selbst sind: Sie sind ein in der Bibliothek implementiertes Konstrukt mit einigen gelegentlichen syntaktischen Zuckerbeschichtungen auf der Oberseite um sie weniger schmerzhaft zu machen.
Die direkte Folge davon ist, dass die Sprache einen großen Teil ihrer Komplexität vor Ihren Augen verbirgt und Sie für die versteckten Nebenwirkungen bezahlen, weil Sie sich angewöhnen, sie genau wie eine atomare Einheit auf niedriger Ebene zu betrachten andere primitive Typen (wie durch die Antwort mit den höchsten Bewertungen und andere erklärt).
Implementierungsdetails
Gute alte Reihe
Eines der Elemente dieser zugrunde liegenden "Komplexität" ist, dass die meisten String-Implementierungen auf die Verwendung einer einfachen Datenstruktur mit zusammenhängendem Speicherplatz zurückgreifen würden, um den String darzustellen: Ihr gutes altes Array.
Dies ist jedoch sinnvoll, da der Zugriff auf die gesamte Zeichenfolge schnell erfolgen soll. Dies bedeutet jedoch möglicherweise schreckliche Kosten, wenn Sie diese Zeichenfolge manipulieren möchten. Der Zugriff auf ein Element in der Mitte ist schnell, wenn Sie wissen, nach welchem Index Sie suchen , aber wenn Sie nach einem Element suchen , das auf einer Bedingung basiert, ist dies nicht der Fall.
Das Zurückgeben der Zeichenfolge kann sogar kostspielig sein, wenn Ihre Sprache die Länge der Zeichenfolge nicht zwischenspeichert und sie zum Zählen von Zeichen durchlaufen muss.
Aus ähnlichen Gründen erweist sich das Hinzufügen von Elementen zu Ihrer Zeichenfolge als kostspielig, da Sie höchstwahrscheinlich Speicher neu zuweisen müssen, damit dieser Vorgang ausgeführt werden kann.
Daher verfolgen verschiedene Sprachen unterschiedliche Ansätze für diese Probleme. Java hat sich beispielsweise die Freiheit genommen, seine Zeichenfolgen aus bestimmten gültigen Gründen (Caching-Länge, Thread-Sicherheit) unveränderlich zu machen, und seine veränderlichen Gegenstücke (StringBuffer und StringBuilder) werden sich dafür entscheiden, Größe mithilfe größerer Blöcke zuzuweisen, die nicht zugeordnet werden müssen jedes Mal, sondern hoffen auf Best-Case-Szenarien. Es funktioniert im Allgemeinen gut, aber die Kehrseite ist, manchmal für Gedächtnisstörungen zu bezahlen.
Unicode-Unterstützung
Auch und gerade deshalb, weil die syntaktische Zuckerbeschichtung Ihrer Sprache dies vor Ihnen verbirgt, um gut zu spielen, halten Sie es oft nicht für Unicode-Unterstützung (insbesondere solange Sie es nicht wirklich brauchen) und gegen die Wand stoßen). Und einige Sprachen, die vorausschauend denken, implementieren keine Strings mit darunter liegenden Arrays von einfachen 8-Bit-Zeichenprimitiven. Sie wurden in UTF-8 oder UTF-16 gebacken oder was-hast-du-Unterstützung für Sie, und die Folge ist ein enorm höherer Speicherverbrauch, der oftmals nicht benötigt wird, und eine längere Verarbeitungszeit zum Zuweisen von Speicher, Verarbeiten der Zeichenfolgen. und implementieren Sie die gesamte Logik, die mit der Manipulation von Codepunkten einhergeht.
Das Ergebnis all dessen ist, dass, wenn Sie im Pseudocode etwas Äquivalentes tun zu:
hello = "hello,"
world = " world!"
str = hello + world
Es kann sein, dass es trotz aller Bemühungen der Sprachentwickler nicht so ist, wie Sie es möchten:
a = 1;
b = 2;
shouldBeThree = a + b
Im Anschluss möchten Sie vielleicht lesen: