文字列を整数で連結する必要があります。そのために、私はstringstream
を次のように使用しています。
int numPeople = 10;
stringstream ss;
ss << "Number of people is " << numPeople;
そしてそれはうまくいった。しかし、私は以下の方法でそれをやろうとしました:
int numPeople = 10;
stringstream ss << "Number of people is " << numPeople;
そして、私は次のエラーを受け取りました: "'<<'トークンの前に期待される初期化子"
このエラーが発生したのはなぜですか?宣言と同時にstringstream
値を割り当てることができないのはなぜですか?
stringstream ss << "Number of people is " << numPeople;
stringstream
の値を宣言と同時に割り当てることができないのはなぜですか?
これはこれがうまくいくことを望んでいるのと似ています:
int x + 3 + 9;
オブジェクトの定義と値の指定の両方を行う場合、C++ではコンストラクターを呼び出すことができます。これには、コンマで区切られた式のリストが必要です。便宜上、Type variable = value;
表記はType variable(value);
を呼び出すために省略されていますが、単一の値に対してのみ機能します。
int
の場合、コードを簡単に修正できます。
int x = 3 + 9;
...「3 + 9」を最初に個別に評価して、x
に保存する適切な値を与えることができるため、機能します。 int
sの演算子+
に対するコンパイラの動作は、私たちが望むことを行います:int
結果を生成して、x
に格納します。しかし、stringstream
にそれを試してみると...
stringstream ss = "Number of people is " << numPeople; // BROKEN
..."Number of people is " << numPeople
を最初に評価する必要がありますが、これは違法であるため、機能しません。「error C2296: '<<' : illegal, left operand has type 'const char [20]'
」のようなエラーが発生します。stringstream
コンストラクターに有用な値が提供されません。問題は、適用する<<
のオーバーロードにはostream&
型の左側の引数が必要であるため、コンパイラーがビット単位のシフト演算子を適用しようとしていることです。これは数値に対してのみ意味があります。 C++では、=
の右側で評価される値が、最終的に結果の値で行われる割り当てとは無関係に評価される必要があり、その時点で、構築される変数のタイプは、式の評価が試行される方法とは関係ありません。割り当てられた。
stringstream
のコンストラクターを呼び出すには、stringstream
で必要な右側の値を組み合わせる必要があるため、ここでは少し鶏と卵の問題が発生しますが、そのためにはstringstream
が必要です。実際には、一時的なstringstream
を使用してそれを引き出すことができます。
static_cast<std::ostringstream&&>(std::ostringstream() << "Number of people is " << numPeople)
残念ながら、operator<<
オーバーロードはstringstream
基本クラスへの参照を介してostream
sを処理し、ostream&
を返すので、キャストは必要です。手動でstringstream
型にキャストバックして、std::stringstream
moveコンストラクターを呼び出すことができます...
完全なワンライナー構造は、次のようになります...
std::stringstream ss(static_cast<std::ostringstream&&>(std::ostringstream() << "Number of people is " << numPeople));
...しかしそれは熟考するにはあまりにも恐ろしいです。
あなたの感性によっては、マクロが助けになるか悪いと感じるかもしれません...
#define OSS(VALUES) \
static_cast<std::ostringstream&&>(std::ostringstream() << VALUES)
std::stringstream ss(OSS("Number of people is " << numPeople));
FWIW、マクロを使用して文字列を作成することもできます...
std::string s(OSS("Number of people is " << numPeople).str());
stringstream
を作成するだけです-オプションでコンストラクタに単一のstring
を提供し、2番目のステートメントでoperator<<
を使用します。
std::stringstream ss;
ss << "Number of people is " << numPeople;
これは非常に読みやすいです。移動構築では、最適化後、2つのステートメントを優先するパフォーマンス上の理由はおそらくありません。
C++ 11で導入された to_string()
オーバーロードは、string
と連結または連結する整数値が1つまたは2つある場合に便利です。
std::string s = "Number of people is " + std::to_string(numPeople);
ただし、これは非効率的かもしれません(必要に応じてコンパイラの最適化機能を確認してください)。各std::to_string()
は、独立したstd::string
インスタンスに動的にバッファを割り当てる可能性が高く、個々の連結にテキストの追加コピーが含まれる可能性があります、および元の動的に割り当てられたバッファを拡大する必要がある場合、それらの一時的なstd::string
sのほとんどは、破棄中に割り当て解除に時間がかかります。
C++ 03にはmoveコンストラクターがなかったため、テンポラリで std::ostringstream::str()
メンバー関数を使用して、名前付きのstd::string
の追加のディープコピーを取得する必要がありました。 stringsteam
...
stringstream ss(static_cast<std::ostringstream&>(std::ostringstream() << "Number of people is " << numPeople).str());
このC++ 03コードでは、動的なメモリ割り当てとコンテンツのコピーが重複する可能性があるため、構築に続くストリーミングの方が適しています。
Stringbufは、値を追加する前に初期化する必要があります。 stringstreamはオブジェクトです。
行うことにより:
std::stringstream ss;
基本的に、アプリケーションで追加される値を処理するためのスペースを割り当てることができます。