Ich lese Accelerated C ++ von Koenig. Er schreibt: "Die neue Idee ist, dass wir + verwenden können, um einen String und ein String-Literal zu verketten - oder zwei Strings (aber nicht zwei String-Literale).
Gut, das macht wohl Sinn. Nun zu zwei getrennten Übungen, die dies beleuchten sollen.
Sind die folgenden Definitionen gültig?
const string hello = "Hello";
const string message = hello + ",world" + "!";
Jetzt habe ich versucht, das oben genannte auszuführen und es hat funktioniert! Also war ich glücklich.
Dann versuchte ich die nächste Übung zu machen;
const string exclam = "!";
const string message = "Hello" + ",world" + exclam;
Das hat nicht funktioniert. Jetzt verstehe ich, dass es etwas damit zu tun hat, dass Sie nicht zwei String-Literale verketten können, aber ich verstehe den semantischen Unterschied nicht, warum ich es geschafft habe, das erste Beispiel zum Laufen zu bringen (ist nicht ", world" und "! "zwei String-Literale? Sollte das nicht funktioniert haben?), aber nicht das zweite.
const string message = "Hello" ",world" + exclam
(zB das erste weglassen+
) sollte gut funktionieren."Hello" + ", world!"
wenn Sie können"Hello, world!"
. Wie üblich bietet C ++ eine fantastische und einfache Problemumgehung für ein wahrgenommenes Problem. :-)"Hello" ", world!"
(ohne das+
). Es gibt eine Reihe von Beschwerden, die man über C ++ machen könnte, aber ich denke nicht, dass die Behandlung hier eine davon ist. Es ist genau das Gleiche, als ob Sie geschrieben1 / 3 + 1.5
und sich beschwert hätten, weil die Teilung eine integrale Teilung war. Zum Guten oder zum Schlechten funktionieren die meisten Sprachen so."hello" " world" == "hello world"
nützlich, wenn Sie eine lange Zeichenfolge schreiben müssen und nicht möchten, dass sie aus Ihrem Fenster verschwindet, oder wenn Sie sich innerhalb einer Zeilenlängenbeschränkung befinden möchten. Oder wenn eine der Zeichenfolgen in einem Makro definiert ist.Antworten:
Der
+
Operator hat eine Assoziativität von links nach rechts, daher lautet der entsprechende Ausdruck in Klammern:Wie Sie sehen können, werden die beiden Zeichenfolgenliterale
"Hello"
und zuerst",world"
"hinzugefügt", daher der Fehler.Eine der ersten beiden verketteten Zeichenfolgen muss ein
std::string
Objekt sein:Alternativ können Sie erzwingen, dass die zweite
+
zuerst ausgewertet wird, indem Sie diesen Teil des Ausdrucks in Klammern setzen:Es ist sinnvoll, dass Ihr erstes Beispiel (
hello + ",world" + "!"
) funktioniert, dastd::string
(hello
) eines der Argumente ganz links ist+
. Das+
heißt, das Ergebnis ist einstd::string
Objekt mit der verketteten Zeichenfolge, und das Ergebnisstd::string
wird dann mit der verketteten Zeichenfolge verkettet"!"
.Der Grund , warum Sie zwei Zeichenfolgenliterale nicht mit verketten können
+
, liegt daran, dass ein Zeichenfolgenliteral nur ein Array von Zeichen ist (aconst char [N]
wobeiN
die Länge der Zeichenfolge plus eins für den Nullterminator ist). Wenn Sie ein Array in den meisten Kontexten verwenden, wird es in einen Zeiger auf sein Anfangselement konvertiert.Wenn Sie also versuchen,
"Hello" + ",world"
zweiconst char*
s zusammen zu addieren , was nicht möglich ist (was würde es bedeuten, zwei Zeiger zusammen zu addieren?), Und wenn dies der Fall wäre, würde es nicht das tun, was Sie tun wollte es tun.Beachten Sie, dass Sie Zeichenfolgenliterale verketten können, indem Sie sie nebeneinander platzieren. Die folgenden beiden sind beispielsweise gleichwertig:
Dies ist nützlich, wenn Sie ein langes Zeichenfolgenliteral haben, das Sie in mehrere Zeilen aufteilen möchten. Es müssen jedoch Zeichenfolgenliterale sein: Dies funktioniert nicht mit
const char*
Zeigern oderconst char[N]
Arrays.quelle
const string message = "Hello" + (",world"+exclam);
aufgrund der expliziten Klammerung (ist das ein Wort?).const string message = ((hello + ",world") + "!");
"Hello" ",world"
Syntax nicht nur zum Aufteilen in mehrere Zeilen nützlich ist, sondern auch, wenn eines der Zeichenfolgenliterale ein Makro ist (oder sogar beide). Dann erfolgt die Verkettung in der Kompilierungszeit.Sie sollten immer auf Typen achten .
Obwohl sie alle scheinen wie Saiten,
"Hello"
und",world"
sind Literale .Und in Ihrem Beispiel
exclam
ist einstd::string
Objekt.C ++ hat eine Operatorüberladung, die ein
std::string
Objekt nimmt und ihm eine weitere Zeichenfolge hinzufügt. Wenn Sie einstd::string
Objekt mit einem Literal verketten , wird das entsprechende Casting für das Literal vorgenommen.Wenn Sie jedoch versuchen, zwei Literale zu verketten, kann der Compiler keinen Operator finden, der zwei Literale verwendet.
quelle
std::string
mit einem anderenstd::string
, einem Zeichenarray oder einem einzelnen Zeichen bietet .Ihr zweites Beispiel funktioniert nicht, da es
operator +
für zwei Zeichenfolgenliterale kein Nein gibt . Beachten Sie, dass ein Zeichenfolgenliteral nicht vom Typstring
, sondern vom Typ istconst char *
. Ihr zweites Beispiel funktioniert, wenn Sie es folgendermaßen überarbeiten:quelle
Seit C ++ 14 können Sie zwei echte String-Literale verwenden :
oder
quelle
In Fall 1 erhalten Sie aufgrund der Reihenfolge der Operationen:
(Hallo + ", Welt") + "!" was zu hallo + "!" und schließlich zu hallo
In Fall 2 erhalten Sie, wie James bemerkte, Folgendes:
("Hallo" + ", Welt") + exclam, das ist das Concat von 2 String-Literalen.
Hoffe es ist klar :)
quelle
Der Unterschied zwischen einer Zeichenfolge (oder genauer gesagt
std::string
) und einem Zeichenliteral besteht darin, dass für letzteres kein+
Operator definiert ist. Aus diesem Grund schlägt das zweite Beispiel fehl.Im ersten Fall kann der Compiler ein geeignetes finden,
operator+
wobei das erste Argument astring
und das zweite ein Zeichenliteral (const char*
) ist, also hat er das verwendet. Das Ergebnis dieser Operation ist wieder astring
, daher wird derselbe Trick beim Hinzufügen wiederholt"!"
.quelle