web-dev-qa-db-ja.com

intをstd :: stringに追加します

intstd::stringに追加する2つの異なる方法を試しましたが、驚いたことに、異なる結果が得られました。

#include <string>

int main()
{
    std::string s;
    s += 2;     // compiles correctly
    s = s + 2;  // compiler error

    return 0;
}

+=演算子を使用すると正常にコンパイルおよび動作しますが、+演算子を使用すると失敗します。

質問は std :: stringとintを連結する方法 のようなものではないと思います

その質問では、+=演算子を使用する答えはありません。そして、+=+std::string演算子の違いは、疑問を解決するための鍵です。

率直に言って、この質問は、c ++の習得が非常に難しい理由を説明する良い例です。

37
navylover

TL; DRoperator+=class stringのクラスメンバー関数であり、operator+はテンプレート関数です。

標準クラスtemplate<typename CharT> basic_string<CharT>にはオーバーロード関数basic_string& operator+=(CharT)があり、文字列はbasic_string<char>にすぎません。

s += 2では、下位の型に適合する値をその型に自動的にキャストできるため、2はnotとしてintとして扱われますが、代わりにcharとして扱われます。 exactlys += '\x02'と同じ効果があります。 ASCIIコード2(STX)の文字が追加され、not文字 '2'(ASCIIで) _値50、または0x32)。

ただし、stringにはstring operator+(int)のようなオーバーロードされたメンバー関数がありません。s + 2は有効な式ではないため、コンパイル中にエラーがスローされます。 (詳細は下記)

次の方法で、stringでoperator +関数を使用できます。

s = s + char(2); // or (char)2
s = s + std::string(2);
s = s + std::to_string(2); // C++11 and above only

なぜ2がoperator+charに自動的にキャストされないのか心配な人のために、

template <typename CharT>
  basic_string<CharT>
  operator+(const basic_string<CharT>& lhs, CharT rhs);

上記はプロトタイプです[注意] s + 2のプラス演算子の場合、およびテンプレート関数であるため、operator+<char>operator+<int>の両方の実装が必要です。これは競合しています。詳細については、「 自動ダウンキャストがテンプレート関数に適用されないのはなぜですか? 」を参照してください

一方、operator+=のプロトタイプは次のとおりです。

template <typename CharT>
class basic_string{
    basic_string&
      operator+=(CharT _c);
};

ここにテンプレートはありません(クラスメンバー関数です)。したがって、コンパイラは、CharT型がクラス実装からcharであると推測し、int(2)char(2)に自動的にキャストされます。


注意: C++標準インクルードソースからコピーすると、不要なコードが削除されます。これには、読みやすくするために、テンプレートクラス「basic_string」のtypename 2および3(TraitsおよびAllocator)、および不要なアンダースコアが含まれます。

47
iBug

s += 2;は、あなたが思っていることをしていない。オーバーロードされた+=演算子をcharに呼び出します。 notcharacter'2'を追加しますが、value2の文字を追加します、結果はプラットフォームで使用されるencodingに依存します。

s + 2のコンパイルを許可するために定義された演算子オーバーロードはありません1。したがって、エラー。

両方の場合の解決策は、intリテラル2ではなくstd::to_string(2)を使用することです。


1 本質的には、operator+=はテンプレート関数ではなく、std::operator+はテンプレート関数であり、オーバーロード解決はテンプレート関数よりも非テンプレート関数を優先するためです。

43
Bathsheba

stringに追加する正しい方法は

std::string s;
s += std::to_string(2);
s = s + std::to_string(2);
12
CoryKramer

@CoryKramerの答えは、文字列に整数を追加する正しい方法を提供しますが、命令s = s + 2がコンパイルされない理由を説明しません。

2つの命令の違いは、最初の命令ではstd::stringの-​​ + =演算子 を使用しますが、2番目の命令では、コンパイラが2を文字列。

intstd::stringの間に暗黙的な変換はありません。ただし、intcharにキャストできるため、s += 2worksが機能するのはこのためです。

2
Xatyrian