符号なし型には 3 つの特徴があり、そのうちの 1 つは質的に「良い」もので、もう 1 つは質的に「悪い」ものです。
- 同じサイズの符号付き型の 2 倍の値を保持できます (良い)。
- バージョン (つまり、
size_t
32 ビット マシンでは 32 ビット、64 ビット マシンでは 64 ビットなど) は、メモリ (アドレス、サイズなど) を表すのに役立ちます (ニュートラル)。
- それらは 0 未満で折り返されるため、ループで 1 を減算したり、-1 を使用して無効なインデックスを表すと、バグ (悪い) が発生する可能性があります。 符号付きの型も折り返されます。
vector
上記の最初の 2 つの理由から、STL は unsigned 型を使用します。これは、 andなどの配列のようなクラスの潜在的なサイズを制限しないためdeque
です (ただし、データ構造に 4294967296 個の要素が必要になる頻度を疑問視する必要があります)。負の値は、ほとんどのデータ構造に対する有効なインデックスにはならないためです。そしてなぜならsize_t
は、構造体のサイズや、文字列の長さなどの関連するものなど、メモリに関係するものを表すために使用する正しい型です (以下を参照してください)。これは、必ずしもインデックスやその他のものに使用する正当な理由ではありません。ループ変数などの非メモリ目的。C++ でこれを行うのがベスト プラクティスである理由は、一種の逆構造です。これは、コンテナや他のメソッドで使用されるものであり、一度使用すると、同じ問題を回避するために残りのコードを一致させる必要があるためです。
値が負になる可能性がある場合は、signed 型を使用する必要があります。
値が負にならない場合は、unsigned 型を使用する必要があります('should not' とは異なる可能性があります)。
size_t
メモリ サイズ(の結果sizeof
、多くの場合、文字列の長さなど)を処理するときに使用する必要があります。コードがコンパイルされるプラットフォームと一致するため、使用するデフォルトの符号なし型として選択されることがよくあります。たとえば、文字列の長さは、文字列size_t
が 0 個以上の要素しか持てないためであり、16 ビット長など、プラットフォームで表現できるものより文字列の長さメソッドを任意に短く制限する理由がないためです。 (0-65535) 32 ビット プラットフォーム。注(コメンターのMorwenに感謝)std::intptr_t
またはstd::uintptr_t
概念的に類似している-プラットフォームに常に適切なサイズであり、ポインターではないものが必要な場合はメモリアドレスに使用する必要があります。注 2 (コメンターrubenvb に感謝size_t-1
)の値により、文字列は要素のみを保持できますnpos
。詳細は以下。
つまり、-1 を使用して無効な値を表す場合は、符号付き整数を使用する必要があります。ループを使用してデータを逆方向に反復処理する場合、ループ構成が正しいかどうか確信が持てない場合は、符号付き整数の使用を検討する必要があります (他の回答の 1 つに記載されているように、それらは簡単に間違えられます)。 、コードが機能することを確認するためにトリックに頼るべきではありません-コードにトリックが必要な場合、それは多くの場合危険信号です. さらに、あなたをフォローしてコードを読んでいる人にとっては、理解しにくくなります。これらは両方とも、上記の@Jasmin Grayの回答に従わない理由です。
イテレータ
ただし、整数ベースのループを使用してデータ構造の内容を反復処理することは、C++ で行うには間違った方法であるため、ある意味では、ループの符号付きと符号なしをめぐる議論は意味がありません。代わりにイテレータを使用する必要があります。
std::vector<foo> bar;
for (std::vector<foo>::const_iterator it = bar.begin(); it != bar.end(); ++it) {
// Access using *it or it->, e.g.:
const foo & a = *it;
これを行うと、キャスト、署名などについて心配する必要はありません。
イテレーターは、逆方向に反復するために、順方向 (上記のように) または逆方向にすることができます。の同じ構文を使用します。it != bar.end()
これend()
は、基礎となる概念配列、ツリー、またはその他の構造の終了ではなく、反復の終了を通知するためです。
つまり、「STL コンテナーを操作するときに int または unsigned int を使用する必要がありますか?」という質問に対する答えです。は「どちらでもない。代わりに反復子を使用してください。 詳細を読む:
何が残っていますか?
ループに整数型を使用しない場合、何が残るでしょうか? データに依存する独自の値ですが、あなたの場合、無効な値に -1 を使用することが含まれます。これは簡単です。サイン入り使用。一貫性を保つだけです。
私は、列挙型などの自然な型を使用することを強く信じており、符号付き整数はこれに適合します。それらは、私たちの概念的な期待とより密接に一致しています。心とコードが一致していれば、バグのあるコードを書く可能性は低くなり、正確でクリーンなコードを表現力豊かに書く可能性が高くなります。