此代码将无法编译:
fn main() {
let m1 = vec![1, 2, 3];
let m2 = vec![&m1, &m1, &m1];
let m3 = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
for i in &m2 {
for j in i {
println!("{}", j);
}
}
for i in &m3 {
for j in i {
println!("{}", j);
}
}
}
error[E0277]: the trait bound `&&std::vec::Vec<{integer}>: std::iter::Iterator` is not satisfied
--> src/main.rs:8:18
|
8 | for j in i {
| ^ `&&std::vec::Vec<{integer}>` is not an iterator; maybe try calling `.iter()` or a similar method
|
= help: the trait `std::iter::Iterator` is not implemented for `&&std::vec::Vec<{integer}>`
= note: required by `std::iter::IntoIterator::into_iter`
m2
与m3
的不同之处在于m3
没有引起任何问题,但是m2
阻止编译?m3
)看起来很笨重。
m2
与m3
有什么不同......
逐步检查类型。 m1
的类型为Vec<isize>
(它也可以是任何其他整数类型,但我认为它现在是isize
)。为什么?因为vec![]
宏中的元素是isize
类型。现在你要创建m2
:
let m2 = vec![&m1, &m1, &m1];
这个宏中元素的类型是什么?好吧,我们已经说过m1
有Vec<isize>
类型,所以&m1
有&Vec<isize>
类型。因此得到的m2
类型是Vec<&Vec<isize>>
(一个充满对其他向量的引用的向量)。
然而,m3
是Vec<Vec<isize>>
类型,因为(外部)vec![]
宏中的元素是Vec<isize>
类型(没有参考!)。
提示:to easily check the type of any variable(如foo
),类型:
let _: () = foo;
这将导致编译器错误,告诉您foo
的类型。
...这样
m3
没有问题,但m2
阻止汇编?
现在我们知道了m2
和m3
的类型,让我们看一下循环。 for
通过接受实现IntoIterator
的东西来循环工作。您正在传递&m2
,其类型为&Vec<&Vec<isize>>
(请注意两个引用)。 We can see,IntoIterator
确实用于引用向量:
impl<T> IntoIterator for &Vec<T> {
type Item = &T
// ...
}
这意味着你得到一个迭代器,它吐出对内部类型T
(type Item = &T
)的引用。我们内部类型的m2
是&Vec<isize>
,所以我们将获得&&Vec<isize>
类型的项目(两个引用!)。您的变量i
具有此类型。
然后你想用这个内循环再次迭代:
for j in i { ... }
但i
有这种双引用类型,并没有针对该类型的IntoIterator
的实现。要迭代它,你必须取消引用它,如:
for j in *i { ... }
甚至更好:使i
成为&Vec<isize>
(一个参考!)类型,通过在外部循环中使用模式匹配将其剥离:
for &i in &m2 { ... }
你的m3
循环也是这样,但由于m3
属于另一种类型(少了一个参考),它可以工作(我希望你能看出原因)。
是否有更简单的方法来创建向量的矢量...到任何所需的深度
即使m2
工作,它也不会与m3
保持相同的价值。要制作m2
类型的Vec<Vec<isize>>
(如m3
),你应该clone
m1
而不是参考它。
let m2 = vec![m1.clone(), m1.clone(), m1.clone()];
我们可以通过使用宏的vec![_; _]
形式做得更好:
let m2 = vec![m1; 3]; // three times the value of `m1`
作为最后一点,你应该考虑不使用嵌套的Vec
s。嵌套会产生开销,因为值分布在整个内存中而不是在一个位置。