I tested the following code but both for loops produced same data type which is &i32.
AFAIK, into_iter() should consume the data but it didn't.
Could someone explain why?
fn main() {
let v = vec![1, 2, 3];
sub(&v);
}
fn sub(v: &Vec<i32>) {
for n in v.into_iter() { // <-- into_iter() does not consume v and n is &i32
print!("{n}");
}
for n in v.iter() {
print!("{n}");
}
}
v has type &Vec<i32> so naturally you are calling <&Vec<i32> as IntoIterator>::into_iter instead of <Vec<i32> as IntoIterator>::into_iter which consume the data.
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T, A: Allocator> IntoIterator for &'a Vec<T, A> {
type Item = &'a T;
type IntoIter = slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
Calling into_iter() over &Vec<T> actually returns just self.iter().
I was just confused because all basic examples showed calling into_iter() removed the variable.
Thank you !
See this post by me for some more examples on Playground. It can feel a bit confusing indeed, but makes sense in my opinion. (Regarding the examples in the other post: providing no method is like invoking into_iter.)
An explicit into_iter (on the !Copy receiver, and where you have !Copy items) is needed when we need explicit conversion into an iterator (e.g. use it without a for loop), but don't want to retrieve references.
I saw your great post. It was very helpful and I have one question.
// These are equivalent if `r` is a `&Vec`:
let r = &v;
for x in r.iter() {
println!("{x}")
}
for x in r {
println!("{x}")
}
// `&Vec` implements `Copy`, so the previous loop didn't consume `r`:
for x in r {
println!("{x}")
}
Here you mentioned that:
&Vec implements Copy, so the previous loop didn't consume r
Does that mean the x in the last (and previous) loop is a copied version of original vector elements?
If so, type of x should be i32 but rust-analyzer says x is &i32 type.
And also when I changed vector to have String elements which is not a copy type, it worked correctly.
Could you explain what I am misunderstanding?
v is a Vec<i32> which does not implement Copy and would require explicit cloning
r is a &Vec<i32> which does implement Copy (as all references implement Copy)
the type of x depends on the particular version of the loop
In this loop…
…x is of type &i32, so it's a reference to the original vector element(s).
See the following example where the elements of the Vec are Strings, so being !Copy:
fn main() {
let v: Vec<String> = vec!["Hello".to_string(), "World".to_string()];
let r = &v;
// now `r` is `Copy`, but
// neither `v` nor `v[0]` (or `v[1]`) is `Copy`
for s in r {
let s: &String = s; // s is a `&String` here
println!("{s}");
}
// we can repeat this because `r` is `Copy` and
// wasn't consumed by the `for` statement
for s in r {
let s: &String = s; // s is a `&String` here
println!("{s}");
}
}