std::vector objects; //then later int size = (int)objects.size(); for( int i = 0; i < size; ++i ) { process( objects[i] ); }
3
0
私はC ++プロジェクトをレビューしていますが、以下を効果的に確認しています:
std::vector objects; //then later int size = (int)objects.size(); for( int i = 0; i < size; ++i ) { process( objects[i] ); }
vector :: size()は `size_t`を返しますが、これは
int`のサイズとは関係のないサイズにすることができます。 sizeof(int)== sizeof(size_t)`であっても、 `int`は署名されており、
size_t`のすべての可能な値を保持することはできません。 したがって、上記のコードは非常に長いベクトルの下部のみを処理でき、バグが含まれています。 正しい方法は、 size`変数とループインデックスの両方に
size_t`を使用することです。
それは、著者がなぜこれを書いたのか興味がありますか?
私の唯一の推測は、最初に `(int)`キャストを省略し、コンパイラがVisual C ++ C4018のようなものを出力したことです。警告:
warning C4018: '<' : signed/unsigned mismatch
そのため、コンパイラの警告を回避する最善の方法は、単純に size_t`を
int`にキャストしてコンパイラをシャットダウンすることです。
そのCキャストの他の考えられる正気な理由はありますか?
4 Answer
9
CとC ++の両方でのCキャストの圧倒的な使用は、コンパイラーを停止させることであり、それが何を伝えているかを理解しようとする努力をほとんど、またはまったくしません。 悲しいですが本当。
9
いいえ、それがおそらく理由です。 加えて、ベクトルがおそらく長すぎてサイズを切り捨てる危険性がないという事実(アプリ。 開発者はそれを知っているでしょう)。
そして… 多分、プログラムのある部分で、彼は実際に「サイズ」をint型の何かと比較したので、サイズを「size_t」型にすると1か所で修正されますが、どこか別の場所で壊れます。
4
明白な答えは、使用することです:
size_t size = objects.size(); for( size_t i = 0; i < size; ++i ) { process( objects[i] ); }
または教育的に正しいこと:
typedef std::vector::size_type s_t; s_t size = objects.size(); for (s_t i=0; i
OTOH、ループを自分で書く必要があることが確実でない限り、一般にアルゴリズムを使用する方が良いでしょう:
std::foreach(objects.begin(), objects.end(), process);
-4
unsigned int size = (int)objects.size(); for( unsigned int i = 0; i < size; ++i ) { process( objects[i] ); }