web-dev-qa-db-ja.com

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

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つの文字列リテラル?これは機能しませんか?).

115
Arthur Collé
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]配列では機能しません。

132
James McNellis

typesに常に注意する必要があります。

それらはすべて文字列のように見えますが、"Hello"",world"リテラルです。

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

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

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

8
Yochai Timmer

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

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

ケース1では、操作の順序が原因で次の結果が得られます。

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

ケース2では、ジェームズが述べたように、次のようになります。

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

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

2
Stephen

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

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

1
Péter Török