5 ms·
>But you didn't quite get away with it. The C++ code increments the value in the array through the iterator, while the above Rust increments the iterator (err,
by Eerie 10y ago
>But you didn't quite get away with it. The C++ code increments the value in the array through the iterator, while the above Rust increments the iterator (err, index) itself. So it doesn't produce the same result.
I have to admit that I don't understand you here. Can you elaborate on the difference between the two programs?
- ridiculous_fish 10y agoSure. The C++: for (iter = foo.begin(); iter != foo.end(); ++iter) { *iter += 1; ... Here `iter` is a pointer. We dereference it and increment the result. This adds 1 to every value in the `foo` vector. The Rust: for mut iter in 0..foo.len() { iter += 1; ... Here `iter` is an array index, and `iter += 1` increments that index. The contents of the `foo` vector are not modified.
- Eerie 10y ago>Here `iter` is a pointer. We dereference it and increment the result. This adds 1 to every value in the `foo` vector. Huh? How is `iter` related to foo? When you go `iter += 1` aren't you just incrementing the variable behind iter? Unless... OK, I'm not very familiar with C or C++, totally newb here. Are you doing pointer arithmetics here, when you increment iter? But wait, if you are doing pointer arithmetic, I thought you are not supposed to deref the pointer. Otherwise you are doing arithmetics on the variable behind the pointer, not the pointer itself. Also, with `foo[0] += *iter`, you are just adding iter to the first element of foo, again and again. You are not actually iterating on foo. I'm confused...
- cesarb 10y agoThink of `foo.begin()` as returning a pointer to the first element of the array, or something which acts like it (similar to Rust's `Deref`). Think of `foo.end()` as returning a pointer to a "virtual" element after the last element of the array. Then `++iter` increments this pointer, so it points to the next element of `foo`. Since `iter` points to an element of `foo`, `* iter` is the element itself. `* iter += 1` adds one to that element. `foo[0] += * iter` takes the current element, adds it to the first element of `foo`, and stores the result as the first element of `foo`. The catch is that, in Rust terms, you have a mutable reference to an arbitrary element of `foo` (the reference being `iter`), and you are getting a mutable reference to another element of `foo` (the reference being `foo[0]`) at the same time. Even worse, in the first iteration, `iter` points to the first element, so `iter` and `foo[0]` are two mutable references to the same location, which exist at the same time! You can't do that in Rust with references (you can with pointers and `unsafe`, and in this case it happens that there is no data race, but...) The correct safe Rust translation would be: let mut foo = vec!(1, 2, 3); for index in 0..foo.len() { foo[index] += 1; foo[0] += foo[index]; } But, for more complicated cases, an equivalent translation won't be as obvious.
- Eerie 10y agoWhat's the advantage of doing pointer arithmetics as opposed to incrementing index variable, like I did?
- rzhikharevich 10y agoThe advantage of iterators is the abstraction. Collections like maps and sets don't even have indexes.