0

文字列に文字のサイズを追加するとどうなるかをテストしたいのですが、以下が結果です。

文字列がヌル文字で終わることはわかっていますが、なぜそのような結果になるのでしょうか?

#include <iostream>
#include <string>
using namespace std;
int main(){
    string a = "" + 'a';    //3
    string b = "" + '1';    //2
    string c = "a" + 'a';   //2
    string d = "1" + '1';   //3
    string e = "\0" + 'a';  //20
    string f = "\0" + '1';  //1
    string g = "a" + '\0';  //1
    string h = "1" + '\0';  //1
    string i = "" + '\0';   //0
    string j = "" + '\0';   //0
    cout << a.size() << endl;
    cout << b.size() << endl;
    cout << c.size() << endl;
    cout << d.size() << endl;
    cout << e.size() << endl;
    cout << f.size() << endl;
    cout << g.size() << endl;
    cout << h.size() << endl;
    cout << i.size() << endl;
    cout << j.size() << endl;
    return 0;
}
4

2 に答える 2

2

あなたのコードはあなたが思っていることをしていません。

文字列リテラルは に減衰しconst char *char整数型です。それらを合計しようとすると、コンパイラは、その意味を理解する最も簡単な方法はchars をints に変換することであることがわかります。そのため、結果は文字列リテラルに対してポインター演算を実行します-たとえば""+'a'、メモリ内の最初の 97 番目の文字に移動します文字列リテラル""('a'プラットフォームで 97 で表される場合)。

これにより、ガーベッジがコンストラクターに渡され、コンストラクターは、ターミネーターが見つかるまで、これらのメモリの場所で見つかったものを構築されstringた内部に格納します。したがって、「奇妙な」結果が得られます(文字列テーブルの正確なメモリレイアウトはコンパイラに依存するため、再現できません)。string\0

もちろん、これはすべて、標準に関する限り未定義の動作です (char追加する場合を除いて、境界外の配列にアクセスしています\0)。

stringコードを意図したとおりに動作させるには、オペランドの少なくとも 1 つが型でなければなりません。

string c = string("a") + 'a';

また

string c = "a" + string("a");

そのため、コンパイラはその include の関連するオーバーロードをoperator+認識しますstd::string

于 2012-12-10T19:58:46.450 に答える
1

ほとんどの初期化子には未定義の動作があります。たとえば、次のことを考慮してください。

string a = "" + 'a';

ポインタにを追加しcharています。charこれにより、ポインタがcharのASCII値だけ進み、結果の(未定義の)C文字列を使用してを初期化しますa

修正するには、上記を次のように変更します。

string a = string("") + 'a';
于 2012-12-10T19:58:14.893 に答える