STL中replace函数误用一例

这是在解JOJ 1170题目的时候遇到的问题,使用replace函数得不到期望结果,调试发现replace函数没有正确执行,查看STL中的源代码发现了问题。针对这个问题重新写一小段测试代码:

  1. #include <algorithm>
  2. #include <cstdio>
  3. #include <ctime>
  4. #include <cstdlib>
  5. using namespace std;
  6. int main() {
  7.     int testArr[16], i;
  8.     srand(time(0));
  9.     for(i = 0; i < 16; i++) 
  10.         testArr[i] = rand() % 5;
  11.     printf("before replace:/n");
  12.     for(i = 0; i < 16; i++)
  13.         printf("%3d", testArr[i]);
  14.     printf("/n");
  15.     printf("after replace testArr[0] with testArr[1]:/n");
  16.     replace(testArr, testArr+16, testArr[0], testArr[1]);
  17.     for(i = 0; i < 16; i++)
  18.         printf("%3d", testArr[i]);
  19.     printf("/n");
  20.     printf("helo world");
  21.     return 0;
  22. }
  23.    

输出结果如下:

before replace:
  2  1  1  4  4  3  2  2  0  3  1  4  0  3  2  0
after replace testArr[0] with testArr[1]:
  1  1  1  4  4  3  2  2  0  3  1  4  0  3  2  0

根据程序的期望,执行后应该把原数组中的所有的2都替换成1,但输出结果却表示程序仅仅把第一个2替换成了1,后面的2都还是保持不变的。

用的编程环境是Emacs+MinGW,用gdb调试执行到replace调用处,输入s命令跟踪到replace的源代码,如下:

这段代码在stl_algo.h头文件中:

  1.   template<typename _ForwardIter, typename _Tp>
  2.     void
  3.     replace(_ForwardIter __first, _ForwardIter __last,
  4.         const _Tp& __old_value, const _Tp& __new_value)
  5.     {
  6.       // concept requirements
  7.       __glibcpp_function_requires(_Mutable_ForwardIteratorConcept<_ForwardIter>)
  8.       __glibcpp_function_requires(_EqualOpConcept<
  9.         typename iterator_traits<_ForwardIter>::value_type, _Tp>)
  10.       __glibcpp_function_requires(_ConvertibleConcept<_Tp,
  11.         typename iterator_traits<_ForwardIter>::value_type>)
  12.       for ( ; __first != __last; ++__first)
  13.         if (*__first == __old_value)
  14.               *__first = __new_value;
  15.     }

执行到这里,还是看不出来问题,单步执行并用disp命令查看__old_value和__new_value的时候才发现,在第一次替换操作执行之后,__old_value竟然变成了__new_value,所以后面就不会再进行任何替换操作了。

出现问题的原因是什么呢?显然是因为replace函数后两个参数是const T&型的,当使用

replace(testArr, testArr+16, testArr[0], testArr[1]);

来调用时,传进去的不是testArr[0]的值,而竟然是testArr[0]的地址!!!

把上述调用修改成:

replace(testArr, testArr+16,(int) testArr[0],(int) testArr[1]);

这样调用才不会出现问题。

 

同样的代码在VC6.0中也是同样的问题。而且在online judge上也是这样。按照以前的那种调用写法,提交上去得了个wrong answer,写成后一种调用,就accepted了。

你可能感兴趣的:(编程,function,测试,emacs)