2つの文字列リテラルを連結する


121

KoenigによるAccelerated C ++を読んでいます。彼は、「新しい考え方は、+を使用して文字列と文字列リテラルを連結できる、つまり、2つの文字列(2つの文字列リテラルではない)を連結できるということです。

結構、これは私が思うに理にかなっています。次に、これを明らかにするための2つの個別の演習に移ります。

次の定義は有効ですか?

const string hello = "Hello";

const string message = hello + ",world" + "!";

今、私は上記を実行しようとしましたが、うまくいきました!嬉しかったです。

それから私は次の練習をしようとしました。

const string exclam = "!";

const string message = "Hello" + ",world" + exclam;

これは機能しませんでした。これで、2つの文字列リテラルを連結できないという事実と関係があることを理解していますが、なぜ最初の例を機能させたのか( "、world"と "!"ではない)の意味上の違いは理解できません。 "2つの文字列リテラル?これはうまくいかなかったのではないでしょうか?)しかし2つ目はうまくいきませんでした。


4
const string message = "Hello" ",world" + exclam(例:最初のものを省略+)shoudは問題なく動作します。
n0rd

1
@Joe- "Hello" + ", world!"できるとき、なぜだれもが書くでしょう"Hello, world!"。いつものように、C ++には知覚された問題に対する素晴らしくシンプルな回避策があります。:-)
Bo Persson、

2
あなたが定義(の#define)を使用する場合、私は考えることができる唯一のことはある@Bo
ジョー・フィリップス

@Joeそれでも、あなたは"Hello" ", world!"(なしで+)書く可能性が高くなります。C ++については多くの不満がありますが、ここでの処理はその1つだとは思いません。それはあなたが書いたかのようにまったく同じ1 / 3 + 1.5であり、部門は積分部門だったので不平を言いました。良くも悪くも、これはほとんどの言語が機能する方法です。
James Kanze、

2
@Bo Persson実際、この機能"hello" " world" == "hello world"は、長い文字列を記述する必要があり、それがウィンドウの外に出たくない場合、または行の長さの制限内に収まるようにする場合に便利です。または、文字列の1つがマクロで定義されている場合。
Dimitar Slavchev

回答:


140
const string message = "Hello" + ",world" + exclam;

+オペレータは、左から右にしている結合性、同等の括弧で囲まれた式があるので:

const string message = (("Hello" + ",world") + exclam);

ご覧のとおり、2つの文字列リテラル"Hello"",world"が最初に「追加」されているため、エラーが発生します。

連結される最初の2つの文字列の1つはstd::stringオブジェクトである必要があります。

const string message = string("Hello") + ",world" + exclam;

別の方法+として、式のその部分を括弧で囲むことにより、最初に2番目を強制的に評価することもできます。

const string message = "Hello" + (",world" + exclam);

()が左端の引数の1つであるhello + ",world" + "!"ため、最初の例()が機能することは理にかなっています。これが評価され、結果は文字列が連結されたオブジェクトになり、その結果がと連結されます。std::stringhello++std::stringstd::string"!"


なぜあなたは2つの文字列リテラルを使用して連結することができない+、それは文字列リテラルは文字の配列だけであるためである(const char [N]ここで、Nヌルターミネータのために、文字列に1を足した長さです)。ほとんどのコンテキストで配列を使用すると、配列はその初期要素へのポインターに変換されます。

したがって、を実行しようとすると"Hello" + ",world"、実際に実行しようとしているのは2つconst char*のを一緒に追加することですが、これは不可能です(2つのポインタを一緒に追加するとはどういう意味でしょうか)。それがしたかった。


文字列リテラルは、隣同士に配置することで連結できることに注意してください。たとえば、次の2つは同等です。

"Hello" ",world"
"Hello,world"

これは、複数の行に分割する長い文字列リテラルがある場合に役立ちます。ただし、文字列リテラルである必要があります。これはconst char*ポインタやconst char[N]配列では機能しません。


3
また、const string message = "Hello" + (",world"+exclam);明示的な括弧があるため、これも機能します(それは単語ですか?)。
Chinmay Kanchi、

1
:最初の例が動作する理由を指摘した場合でも、より完全なものでしたconst string message = ((hello + ",world") + "!");
マーク身代金

ありがとうございました!私はそれが左から右への関連性に関係しているのではないかと疑っていましたが、確信が持てず、この意味の違いは私にはあまり意味がありませんでした。私は答えに感謝します!
ArthurCollé

2
"Hello" ",world"構文は、複数行に分割する場合だけでなく、文字列リテラルの1つがマクロ(またはその両方)の場合にも役立つことを述べておきます。その後、連結はコンパイル時に行われます。
Melebius 2014年

8

タイプには常に注意を払う必要があります

彼らはすべての文字列のように見える、が、"Hello"",world"しているリテラル

そして、あなたの例でexclamは、std::stringオブジェクトです。

C ++には、std::stringオブジェクトを取得して別の文字列を追加する演算子オーバーロードがあります。std::stringオブジェクトをリテラルと連結すると、リテラルに適切なキャストが行われます。

しかし、2つのリテラルを連結しようとすると、コンパイラーは2つのリテラルをとる演算子を見つけることができません。


を別の、文字配列、または単一の文字と連結するためのオーバーロードを提供するstd :: operator +を参照してください。std::stringstd::string
DavidRR 2015

7

operator +2つ目の文字列リテラルがないため、2 番目の例は機能しません。文字列リテラルはタイプstringではなく、タイプであることに注意してくださいconst char *。2番目の例は、次のように修正すると機能します。

const string message = string("Hello") + ",world" + exclam;


2

ケース1では、操作の順序により、次のようになります。

(hello + "、world")+ "!" hello + "!"に解決されます 最後にこんにちは

ケース2では、Jamesが指摘したように、次のようになります。

( "Hello" + "、world")+ 2つの文字列リテラルの連結であるexclam。

それが明確であることを願っています:)


1

文字列(正確にはstd::string)と文字リテラルの違いは、後者の場合、+演算子が定義されていないことです。これが、2番目の例が失敗する理由です。

最初のケースでは、コンパイラーoperator+は最初の引数がa stringで、2番目の引数が文字リテラル(const char*)であるものを見つけることができるため、それを使用しました。その操作の結果は再びであるstringので、それに追加"!"するときに同じトリックを繰り返します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.