这个问题在这里已有答案:
这是我第一次遇到Rust,我正在阅读当前版本的Rust Book中关于向量的章节 . 我之前有过使用其他语言的经验(主要是功能性的,隐藏了以下问题) .
运行以下代码片段(从书中)返回 3
:
fn main() {
let v = vec![1, 2, 3, 4, 5];
let third: &i32 = &v[2];
println!("{}", third);
}
- 我不明白的第一件事是为什么没有引用
println!
宏内的third
. 我希望上面的代码打印v
的第3个元素的内存地址(如C和C中所示),而不是其内容 .
现在考虑代码(这次在 println!
内注意引用):
fn main() {
let v = vec![1, 2, 3, 4, 5];
let third: &i32 = &v[2];
println!("{}", *third);
}
- 为什么上面的代码产生与上面的代码完全相同的输出,好像
*
没有区别?
最后,让我们重写上面的代码片段,完全消除引用:
fn main() {
let v = vec![1, 2, 3, 4, 5];
let third: i32 = v[2];
println!("{}", third);
}
- 为什么最后一个版本产生与前两个版本相同的输出?
v[2]
究竟有什么类型:是&i32
还是i32
?
上述所有内容都是自动解除引用的一种表现形式,只是在前一章中曾经提到过吗? (如果是这样,那么这本书应该被重写,因为它比澄清更令人困惑 . )
1 回答
免责声明:我也在学习Rust,所以请带上一粒盐 .
要了解发生了什么,使用cargo-expand可能会更容易 .
对于代码
我们得到了(我删除了不相关的代码)
对于第一个/最后一个案例,和
对于第二种情况 .
粗略地,这意味着,对于
{}
格式化程序,将分别调用函数fmt
(特征Display
)以引用third
或*third
.让我们应用这个逻辑
第二种情况:
third: &i32
然后*third: i32
,这是impl Display for i32适用的地方 .第一种情况:
third: &i32
,这也是因为impl<', T> Display for &' T(其中T
是i32
)最后一种情况:
third: i32
:与第一种情况相同 . 此外,v[2]
(类型为i32
)的工作原理是因为impl Index for Vec(注意:let third = v[2]
有效,因为impl Copy for i32,即复制语义适用于=
而不是默认的移动语义) .