1

C++ の学習。文字列の最初の文字を取得し、その文字に基づいて新しい文字列を作成し、それを出力したいだけです。

#include <iostream>
using namespace std;

int main(int argc, const char * argv[]) {
    string name = "Jerry";
    char firstCharacter = name.at(0);
    string stringOfFirstCharacter = string(&firstCharacter);
    cout << stringOfFirstCharacter;
    return 0;
}

出力は次のとおりです。

J
Jerry

なぜそれが印刷されているのか、私にはよくわかりませんJerry。何故ですか?

4

4 に答える 4

8

あなたのコードには未定義の動作があります。ポインターを取るコンストラクターの署名は、ヌルで終了charする文字列へのポインターである必要がありますが、これは単一の文字であるため、あなたのケースではそうではありません。

あなたが持っている実装は小さなオブジェクトの最適化を使用しており、「ジェリー」は十分に小さいためstd::string、動的に割り当てられるのではなく、オブジェクト内に格納されると思います。スタック内の 2 つのオブジェクトのレイアウトはたまたま最初firstCharacterに 、次に になりnameます。呼び出すと、最初のヌル文字 (バッファーstd::string(&firstCharacter)内) に到達するまで読み取り、そこで停止します。std::string

于 2013-04-17T20:17:51.677 に答える
3

std::stringからオブジェクトを作成していますchar*( のアドレスを取得しているためfirstCharacter)。文字へのポインターは、 のコンストラクターによって文字自体として解釈されるのではstd::stringなく、null で終わる文字列として解釈されます。

この場合、のアドレスはヌル終了文字列の最初の文字のアドレスではないため、プログラムにはUndefined Behaviorがあります。firstCharacter

あなたがすべきことは次のとおりです。

string stringOfFirstCharacter(1, firstCharacter);
cout << stringOfFirstCharacter;

本当に1文字の文字列を作成したい場合。ただし、文字を標準出力に出力するには、次のように単純に記述できることに注意してください。

cout << firstCharacter;

あるいは:

cout << name.at(0);
于 2013-04-17T20:17:42.613 に答える
2

では、フォームのコンストラクターstring(&firstCharacter)を使用していますstd::string

std::string( const char* s, const Allocator& alloc = Allocator() );

その形式は、 null で終わる文字の配列へのポインタを想定しています。null で終了していない文字へのポインターを渡すのは正しくありません。

文字列を 1 で初期化する意図があるchar場合は、次の形式を使用する必要があります。

string( 1, firstCharacter )
于 2013-04-17T20:17:23.997 に答える
1

使用stringしているコンストラクター (引数を取るchar *もの) は、C スタイルの文字列を単一の文字ではなく C++ 文字列オブジェクトに変換することを目的としています。単一の文字を渡すと、未定義の動作が発生します。

特定のケースでは、の後にメモリにゼロバイトがないように見えるfirstCharacterため、コンストラクターが実行され、すべてが含まれますname

于 2013-04-17T20:17:39.577 に答える