2012-02-24 4 views
0

コンパイルエラーが発生するコードは次のとおりです。私はこれがC++で機能しているはずだと思った。 ここで何が間違っているのか理解できる人は誰でも助けてくれますか?stlコンテナを入力とする関数テンプレート

template < typename elem_type> 
elem_type *find2(std::vector<elem_type>& vec, elem_type value) { 
    for (int i = 0; i < vec.size(); ++i) { 
     if (vec[i] == value) { 
      return &vec[i]; 
     } 
    } 
    return 0; 
} 
int main(int argc, char **argv) { 
    int arr[10] = {1,2,3,4,5,6,7,8,9,10}; 
    std::vector<int> vec(arr, arr+10);  
    int value = 9; 
    int *ptr1 = find2(vec,value); 
} 

1>   d:\personal\work\find\find\find.cpp(25) : see reference to function template instantiation 'elem_type *find2<int>(std::vector<_Ty> &,elem_type &)' being compiled 
1>   with 
1>   [ 
1>    elem_type=int, 
1>    _Ty=int 
1>   ] 

コンパイラはあなたが符号なしに署名したint変数iを比較している。このラインでVisual Studio 11

+2

なぜ完全なエラーメッセージを投稿しないのですか? –

+1

あなたは 'std :: find(arr、arr + 10、9)'を使うことができることを知っていますか? –

+1

私はg ++でコードをコンパイルしましたが、エラーなしでコンパイルしました。私は "#"を追加しました。 "std :: cout << * ptr1 << std :: endl;を追加すると正解を出力します。だからあなたのコンパイラ? – Avi

答えて

0

for (int i = 0; i < vec.size(); ++i) { 

でコンパイルエラーで、次のvec.size()の210の結果。

コンパイラは、このような比較がの暗黙的なプロモーションでは安全でないため警告します。 C++。 isize_tに昇格されます。 iが(仮定的に)負の値であれば、それは非常に大きな値を生成し、したがって予期しない比較結果を生成します。

簡単な治療法は、次にやる例えば

#include <stddef.h> 
    typedef ptrdiff_t Size; 
    typedef Size Index; 

にあると

for (int i = 0; i < Size(vec.size()); ++i) { 

おそらく、明らかに単純に

for (size_t i = 0; i < vec.size(); ++i) { 

を推薦する少なくとも一つの答えを得るでしょうが、これはコンパイラが警告していることと同じ理由で問題がある:リスクは非常に奇妙な取得数として符号なし整数を使用して予想外の結果、バグの結果、暗黙のプロモーション、および一般的に負数から無署名への変換、またはその逆によるものです。

上記鋳造よりもさらに良いことに、

template< class Container > 
    Size countOf(Container const& c) { return v.size(); } 

    template< class Elem, Size n > 
    Size countOf(Elem (&)[n]) { return n; } 

ようcountOf関数を定義してからちょうど

for (int i = 0; i < countOf(vec); ++i) { 

そして、最高を書き、そのインデックスを忘れると使用イテレータ:

for (auto it = vec.begin(); it != vec.end(); ++it) { 
4

インデックスに使用されているインデックスと同じタイプの変数を使用することをお勧めします。コンテナ。この場合、size_tまたはsize_typeが必要です。これらは、ベクトルのsizeおよびoperator[]関数で使用される型に対応しています。

for (size_t i = 0; i < myVector.size(); ++i) 
{ 
    myVector[i]++; 
} 

逆順に反復する必要がある場合は、単に内部インデックスを維持するだけです。

for (size_t i = 0; i < myVector.size(); ++i) 
{ 
    size_t j = myVector.size() - i - 1; 
    myVector[j]++; 
} 

符号付き演算を実行する必要がある場合は、内部キャストを維持してください。

for (size_t i = 0; i < myVector.size(); ++i) 
{ 
    int j = (int)i; 
    myVector[i] += j; 
} 
+0

-1これは、正当な理由がないために、複雑さとバグアトラクター(主に暗黙的な変換を介して)を追加します。 –

+0

[size_t](http://critical.eschertech.com/2010/04/07/danger-unsigned-types-used-here/)を使うことは、議論の余地があるようです。 –

+2

これは規律が出てくるところです。 'i'変数はコレクションを反復するためのものです。複雑な数学を行う必要がある場合は、型を修正するためにローカル変数のキャストを行います。 – TheBuzzSaw

3

基本的な問題は、符号付き整数と符号なし整数を混在させることです。インデックス変数は符号付きの型ですが、ベクトルのsize()メンバー関数は符号なしの型を返します。このようなタイプを混在させるとエラーが発生する可能性があります。 -1のような符号付きの値が符号なしの変数に代入されると、通常は非常に大きな値が結果になります。

標準ライブラリコンテナを反復する慣用方法は、標準ライブラリイテレータを使用することです。

for (std::vector<elem_type>::iterator it=vec.begin(); it<vec.end(); ++it) 
{ 
    if (*it == value) { 
     return &(*it); 
    } 
} 
+1

これも機能します。最終的に、forループのイテレータで実行される数学は、とにかく分離されるべきです。私には、無意味な無署名の値がどれくらいの人がQQしているのかが分かります。 – TheBuzzSaw

関連する問題