views:

436

answers:

10
string::iterator it;
for (it = str.begin(); it < str.end(); it++) 
    cout << *it;
cout << endl;

Why not:

for (int i = 0; i < str.size(); i++)
    cout << str[i];
cout << endl;

It seems that string::iterator does not provide range check either. Why should we use string::iterator rather than index?

Thanks.

A: 

In C++, you can do many things in many different ways. This is one more example. In this case, there is no difference which method to use. But in general, iterators are faster, safer and provide more flexibility amond different types of containers.

alemjerus
A: 

Both works.

The main reason would be consistency: you're iterating over a collection or the characters of a string the same way, by requesting an iterator and making it advance.

I would not say the implementation details of ++it resulting in a pointer increment compared to str[i] involving pointer arithmetics is worth mentioning. And range checking are implementation detail as well.

Gregory Pakosz
+1  A: 

As stated in this question, size() method is not guaranteed to be O(1)

Drakosha
It seems unclear from that thread. A comment mentions that `s.end() - s.begin()` definitely has constant complexity, so one would have to be mad to implement size() with a worse complexity.
UncleBens
Why? Size can be based on strlen()-alike which is O(stringLength). In order to implement size() in O(1) you will need memory...
Drakosha
s.size() cannot be implemented with a strlen()-alike, since std::string may contain any character (including `'\0'`). Also, the string has to keep track where it ends (or its size). Why would you think s.end() and the iterators would be any better, if the string didn't know its length and had to find the end in O(N)?
UncleBens
@UncleBens: If the string does not store its size (it is not required to do so but probably does). Then finding the size() would be O(n). As would finding the size using iterators begin() and end() (doing end() - begin() may not be straight arithmetic as there is no requirement for contiguous memory in strings). But the second loop does not calculate the size, it just keeps incrementing the iterator until it reaches then end.
Martin York
+10  A: 

iterators are a standard interface, by using iterators your can use the same algorithms with different containers. the final decision whether to use them or not is up to you based on usability and readability

example:

using the standard transform algorithm to covert std::string to uppercase:

std::string str= “A String”;
std::transform(str.begin(), str.end(), str.begin(), ::toupper);

will result with str equal to "A STRING"

Alon
what about the specific string::iterator?are there any benefits,for example?
Jichao
@jcyang: Only that if you use iterators, then it works anywhere iterators are expected, and the string can be changed to a char array or a vector or some other container, and your loop will still work.
jalf
In the example above, the method `std::string::begin()` returns a `std::string::iterator`, as with `std::string::end()`. The benefit is that you can use the `std::transform` algorithm. You can't use it with indices.
Thomas Matthews
+2  A: 

Iterators are safer and provide more flexibility as posted by someone else too.In additon an index only can be used for containers that (efficiently) support random access (i.e. direct access to an element at a given position).An iterator is a more general concept. Iterators offer efficient traversal of linked lists, files, and a number of other data structures. It often leads to the generation of more efficient code.

Prasoon Saurav
Iterators are not faster. every test have ever done using them indicates that they are if anything slightly slower.
anon
Thanks, I have corrected my post.
Prasoon Saurav
A: 

In cases where you don't know which class you're iterating over (because it's a template argument), you should use an iterator because not every class that provides an iterator also provides [] (and not every class that does provide [], provides one which works in O(1) time). So by using iterator you'll make sure that the function will work with as many classes as possible (though not with C arrays).

In this specific case, I see no reason to prefer one over the other except personal preference or maybe premature optimization.

sepp2k
+4  A: 

The index can only be used for containers that support random access - direct access to a given position.

The iterator offers a unified way to access any collection/data structure. The flexibility when refactoring your code is immense.

Niels Castle
iterators are so nice.. it seperates the men from the boys IMHO
0A0D
A: 

I assume one further reason why iterators should be preferred over indices is that not all collections support constant-time random access.

For example, if you want the n-th element in a linked list, you need to traverse all preceding elements (with indices 0..n-1) until you get to the n-th element. (This operation takes linear time.)

An (sequential) iterator remembers where it is in a collection and doesn't always have to start again from the beginning when you want the next element. In your example, you don't actually need to access the characters in a string in random order, but only sequentially, so using an iterator will almost certainly be faster (constant-time).

stakx
+2  A: 

Duplicate of:

  1. http://stackoverflow.com/questions/178934/iterators-why-use-them
  2. http://stackoverflow.com/questions/131241/why-use-iterators-instead-of-array-indices

That said, it's a matter of genericity. You can do a lot more with iterators using STL than with array access. Also, if you need to refactor code, and change the string to a vector, list or rope, you wont have to rewrite your code at all.

Finally there's the question of safety in iteration. If you want to access the NEXT character in your loop, with iterators you could do that safely, but increasing the array subscript might segfault on you on the last element, hence needing another check.

Kornel Kisielewicz
+1  A: 

For std::string specifically, i would suggest you use indexes since it supports Random Access and its simpler that way. The only reason its "recommended" to use iterators is because iterators offer a standard interface to access sequences so that if your sequence changed to std::list for example, your iteration code would remain un-affected

lalitm