Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> The bit about broken iterators is actually nice, but in this case could be avoided by handing an external function two const_iterator which then cannot be changed.

No, I think you missed the point, which is iterator invalidation.

http://stackoverflow.com/questions/16904454/what-is-iterator....

It's important to understand that various container methods can cause iterators to point to something else (or even nothing!).

In the example given, push_back could cause all the contents of the vector to be reallocated at a new address to make room for the new element. Any iterators pointing to the old address, including the one used in the for loop, don't get updated in this process.

More details for the interested:

http://kera.name/articles/2011/06/iterator-invalidation-rule...

In contrast, Rust only lets you have more than one reference to an object (like a vector and an iterator) if all of them are immutable. So any container methods that would cause iterator invalidation wouldn't be available inside of a for loop.

EDIT: Re-reading, I realize you might have already understood iterator invalidation, so sorry for the re-explanation, but I'll leave it up there for those that haven't heard of it yet.

I will point out that:

1. This sort of for loop is idiomatic C++ code.

2. C++ compilers don't even warn you when you push_back while having active const_iterators to your vector. Rust does, which is the point of the example. This is a case where C++'s const (logically won't change) is inferior to a stronger immutability guarantee, which Rust provides.



>1. This sort of for loop is idiomatic C++ code.

No. This is C code. In C++ you write:

    std::vector<int> a = { 1, 2, 3 };
    std::cout << std::min_element(a.cbegin(), a.cend()) << std::endl;
You shouldn't be writing a lot of loops in C++. You should be using the algorithms as much as possible.


I'm aware of algorithms and espouse them, but you're not comparing apples to apples. The example is about mutating a collection while iterating over it:

  for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) {
      if (*it < 5)
          v.push_back(5-*it);
  }
...you could do that with std::for_each and a lambda, or maybe some creative use of std::back_inserter, but you'd still have iterator invalidation problems.

The right way to do it might be to use a while loop that uses std::find_if to find the next value to insert, but I'm not sure how you'd arrive at that solution without thinking about iterator invalidation in the first place.

...and the point is that Rust effectively says "you can't iterate over a mutable collection like that" while a less battle-scarred C++ developer might not even notice the problem before deploying to production.


Actually the simplest way to dix that code ils to write

it = v.push_back(5-*it);


Don't use "std::endl" unless you intend to flush the stream (doubtful in this case). It's not a replacement or synonym for "\n".




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: