2012-02-24 47 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>   ] 

編譯器是Visual Studio 11

+2

爲什麼不發佈完整的錯誤信息? – 2012-02-24 05:58:34

+1

你知道你可以使用'std :: find(arr,arr + 10,9)'...? – 2012-02-24 06:03:27

+1

我剛用g ++編譯代碼,編譯時沒有錯誤。我添加了「#包括」。當我添加「std :: cout << * ptr1 << std :: endl;」它輸出正確的答案。那麼......你的編譯器? – Avi 2012-02-24 06:06:57

回答

0

在這一行,

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

你是比較有符號int變量i無符號size_t結果vec.size()

編譯器發出警告,因爲在C++中,面對隱式升級時這樣的比較是不安全的。 i被提升爲size_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) { 

,但是這是有問題出於同樣的原因,編譯器警告:使用無符號整數爲數字風險變得非常怪異以及由於隱式升級以及一般從負數轉換爲無符號,或反之亦然的意外結果,錯誤結果。

甚至比上面的鑄造更好,定義一個countOf功能像

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

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

,然後寫只是

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

而且最好的,忘記該索引和使用迭代器:

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

最好使用與所用索引相同類型的變量 容器。在這種情況下,您需要size_tsize_type。它們與矢量的sizeoperator[]函數中使用的類型相對應。

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由於沒有很好的理由,這增加了複雜性和缺陷吸引力(主要是通過隱式轉換)。 – 2012-02-24 06:36:55

+0

使用[size_t](http://critical.eschertech.com/2010/04/07/danger-unsigned-types-used-here/)似乎是一個有爭議的主題,有趣的是至少可以說。 – 2012-02-24 07:23:49

+2

這是紀律來的地方。'i'變量在這裏迭代一個集合。如果你需要對它進行復雜的數學運算,可以將局部變量轉換爲正確的類型。 – TheBuzzSaw 2012-02-24 19:11:20

3

您遇到的根本問題是混合了有符號和無符號整數。您的索引變量是一個有符號類型,但向量的size()成員函數返回一個無符號類型。像這樣混合類型可能會導致錯誤。如果像-1這樣的有符號值被分配給一個無符號變量,通常會得到一個非常大的值。

迭代標準庫容器的慣用方式是使用標準庫迭代器。

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

這也適用。最終,在for循環迭代器上執行的數學運算總是應該分開。我很難看到人們對可怕的無符號值是多麼懷疑。 – TheBuzzSaw 2012-02-24 20:19:19