现在的位置: 首页 > 综合 > 正文

vector的iterator的错误使用

2013年10月03日 ⁄ 综合 ⁄ 共 2679字 ⁄ 字号 评论关闭

原文如下:(摘自<<c++ standard library>>)

 

 

7.2.6 The Increment and Decrement Problem of Vector Iterators

The use of the increment and decrement operators of iterators includes a strange problem. In general, you can increment and decrement temporary iterators. However, for vectors and strings, you typically can't. Consider the following vector example:

					
   std::vector<int> coll;
   ...
   //sort, starting with the second element
   // - NONPORTABLE version 
   if (coll.size() > 1) {
       coll.sort (++coll.begin(), coll.end());
   }

				

Typically, the compilation of sort() fails. However, if you use, for example, a deque rather than a vector, it will compile. It might compile even with vectors, depending on the implementation of class vector.

The reason for this strange problem lies in the fact that vector iterators are typically implemented as ordinary pointers. And for all fundamental data types, such as pointers, you are not allowed to modify temporary values. For structures and classes, however, it is allowed. Thus, if the iterator is implemented as an ordinary pointer, the compilation fails; if implemented as a class, it succeeds. It always works with deques, lists, sets, and maps because you can't implement iterators as ordinary pointers for them. But for vectors, whether it works depends on the implementation. Usually, ordinary pointers are used. But if, for example, you use a "safe version" of the STL, the iterators are implemented as classes. To make your code portable you should not code as the previous example, using vectors. Instead, you should use an auxiliary object:

					
   std::vector<int> coll;
   ...
   //sort, starting with the second element
   // - PORTABLE version
   if (coll.size() > 1) {
       std::vector<int>::iterator beg = coll.begin();
       coll.sort (++beg, coll.end()); 
   }

				

The problem is not as bad as it sounds. You can't get unexpected behavior because it is detected at compile time. But it is tricky enough to spend time solving it. This problem also applies to strings. String iterators are usually also implemented as ordinary character pointers, although this is not required.

 

 

意思是说vector里面的iterator实际上是个指针类型。所以,coll.begin()返回的是容器存储的首个元素的地址,也就返回了一个指针的值,所以不能对其进行++coll.begin()操作。而通过std::vector<int>::iterator beg另外定义一个变量后,就可以对其进行++beg操作了。

 

如果不是vector,而是list,由于list里面的iterator是一个类,所以可以用list mylist; ++mylist.being()操作。但是sort支持的是randomaccess iterator,所以,不能在sort里使用list的iterator作为参数。下面用iter_swap算法函数演示:

 

 

 #include <iostream>
   #include <list>
   #include <algorithm>
   #include "print.hpp"
   using namespace std;


   int main() 
   {
       list<int> coll;


       //insert elements from 1 to 9
       for (int i=1; i<=9; ++i) {
           coll.push_back(i); 
       }


       PRINT_ELEMENTS(coll);


       //swap first and second value
       iter_swap (coll.begin(), ++coll.begin());


       PRINT_ELEMENTS(coll);


       //swap first and last value
       iter_swap (coll.begin(), --coll.end());

       PRINT_ELEMENTS(coll);
   }

				

The output of the program is as follows:

					
   1 2 3 4 5 6 7 8 9
   2 1 3 4 5 6 7 8 9
   9 1 3 4 5 6 7 8 2

 

 

Note that this program normally does not work if you use a vector as a container. This is because ++coll.begin() and --coll.end() yield temporary pointers (see Section 7.2.6, for details regarding this problem).

 

抱歉!评论已关闭.