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つの文字列リテラル?これは機能しませんか?).
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);
hello + ",world" + "!"
(hello
)は左端のstd::string
の引数の1つであるため、最初の例(+
)が機能することは理にかなっています。その+
が評価され、結果は文字列が連結されたstd::string
オブジェクトになり、結果のstd::string
は"!"
と連結されます。
whyに関しては、+
を使用して2つの文字列リテラルを連結することはできません。これは、文字列リテラルが単なる文字の配列であるためです(const char [N]
where N
nullターミネータの場合、文字列の長さに1を加えたものです)。ほとんどのコンテキストで配列を使用すると、初期要素へのポインターに変換されます。
したがって、"Hello" + ",world"
を実行しようとすると、実際にしようとしているのは、2つのconst char*
sを一緒に追加することです。これは不可能です(2つのポインターを一緒に追加するとはどういう意味ですか)それはあなたが望んでいたことをしないでしょう。
can文字列リテラルを互いに隣り合わせて連結することに注意してください。たとえば、次の2つは同等です。
"Hello" ",world"
"Hello,world"
これは、複数の行に分割する長い文字列リテラルがある場合に便利です。ただし、文字列リテラルである必要があります。これは、const char*
ポインターまたはconst char[N]
配列では機能しません。
typesに常に注意する必要があります。
それらはすべて文字列のように見えますが、"Hello"
と",world"
はリテラルです。
そして、あなたの例では、exclam
はstd::string
オブジェクトです。
C++には、std::string
オブジェクトを受け取り、それに別の文字列を追加する演算子オーバーロードがあります。 std::string
オブジェクトをリテラルと連結すると、リテラルに適切なキャストが行われます。
しかし、2つのリテラルを連結しようとすると、コンパイラーは2つのリテラルを取る演算子を見つけることができません。
2番目の例は、2つの文字列リテラルにoperator +
がないため機能しません。文字列リテラルはstring
型ではなく、const char *
型です。 2番目の例は、次のように修正すると機能します。
const string message = string("Hello") + ",world" + exclam;
ケース1では、操作の順序が原因で次の結果が得られます。
(hello + "、world")+ "!" hello + "!"に解決されますそして最後にこんにちは
ケース2では、ジェームズが述べたように、次のようになります。
( "Hello" + "、world")+ 2つの文字列リテラルの連結であるexclam。
それが明確であることを願っています:)
文字列(正確にはstd::string
)と文字リテラルの違いは、後者には+
演算子が定義されていないことです。これが、2番目の例が失敗する理由です。
最初の場合、コンパイラは適切なoperator+
を見つけることができます。最初の引数はstring
で、2番目は文字リテラル(const char*
)であるため、それを使用します。その操作の結果は再びstring
であるため、"!"
を追加するときに同じトリックを繰り返します。