2012-02-24 46 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