Which style do you prefer? And reason?

fn main() {
	let mut a = String::new();
	let mut b = String::new();

	for s in [&mut a, &mut b].iter_mut() {
		**s = String::from("s");
	}
	for s in vec![&mut a, &mut b].into_iter() {
		*s = String::from("s");
	}
}

First because there is guaranteed to be no allocation.

4 Likes

I have yet to understand why both couldn't cause or prevent an allocation. It seems incoherent.

I don't understand "*' vs "**".
Does someone have a good link?

First, about allocation.
Vecs are stored on the heap. So, by default, if you write vec![/* something */], it means that you ask for some allocation, even if you immediately consume it. Optimizer often can make the into_iter operate directly on input values, but not always.
Arrays, on the other hand, are stored on the stack, not using the heap at all, and so the iteration on them is more effective even if the array creation isn't optimized away (and in many cases it will be).

Second, about dereferences. The rule is simple: one dereference (i.e. one star) removes one level of referencing, so in many cases you simply continue to dereference things until either the type checker stops complaining (and you're good) or borrow checker states that you can't do that (if you were trying to move something out of reference).
In this case, the difference is the following:

  • Array contains references of the type &mut String. Then, you call iter_mut(), getting the iterator which yields references to array items, i.e. &mut &mut String; so you have to use two dereferences to get to the inner String.
  • Vector also contains references of the type &mut String, but it is consumed by calling into_iter() and gives as the iterator which yields the vector items themselves, i.e. &mut String, which must be dereferenced only once.
8 Likes

That was very concise. Thanks.