不了解如何在 Rust 中访问向量的元素

Ale*_* M. 5 pointers reference vector rust

这是我第一次接触 Rust,我正在阅读Rust Book当前版本中关于向量的章节。我之前确实有使用其他语言的经验(主要是函数式语言,其中隐藏了以下问题)。

运行以下代码片段(来自本书)返回3

fn main() {
  let v = vec![1, 2, 3, 4, 5];
  let third: &i32 = &v[2];
  println!("{}", third);
}
Run Code Online (Sandbox Code Playgroud)
  1. 我不明白的第一件事是为什么没有引用宏third内部println!。我本来希望上面的代码打印v(如在 C 和 C++ 中)的第三个元素的内存地址,而不是它的内容。

现在考虑代码(注意这次里面的引用println!):

fn main() {
  let v = vec![1, 2, 3, 4, 5];
  let third: &i32 = &v[2];
  println!("{}", *third);
}
Run Code Online (Sandbox Code Playgroud)
  1. 为什么上面的代码和上面的代码产生完全相同的输出,好像*没有什么区别?

最后,让我们重写上面的代码片段,完全消除引用:

fn main() {
  let v = vec![1, 2, 3, 4, 5];
  let third: i32 = v[2];
  println!("{}", third);
}
Run Code Online (Sandbox Code Playgroud)
  1. 为什么最后一个版本产生与前两个相同的输出?什么类型v[2]确实有:它是 an&i32还是 an i32

以上所有内容是否都是前一章中仅提及一次的自动取消引用的表现?(如果是这样,那么这本书应该重写,因为它比澄清更令人困惑。)

Ta *_*inh 2

免责声明:我也在学习 Rust,所以请对此持保留态度。

要了解发生的情况,使用cargo-expand可能会更容易。

对于代码

fn main() {
  let v = vec![1, 2, 3, 4, 5];
  let third: &i32 = &v[2];
  println!("{}", third);
}
Run Code Online (Sandbox Code Playgroud)

我们得到(我已经删除了不相关的代码)

fn main() {
    ...
    let third: ...
    {
        ::io::_print(::std::fmt::Arguments::new_v1_formatted(                            
            ...
            &match (&third,) {                                                           
                (arg0,) => [::std::fmt::ArgumentV1::new(arg0, ::std::fmt::Display::fmt)],
            },
            ...
        ));
    };
}
Run Code Online (Sandbox Code Playgroud)

对于第一个/最后一个案例,以及

fn main() {
    ...
    let third: ...
    {
        ::io::_print(::std::fmt::Arguments::new_v1_formatted(                            
            ...
            &match (&*third,) {                                                           
                (arg0,) => [::std::fmt::ArgumentV1::new(arg0, ::std::fmt::Display::fmt)],
            },
            ...
        ));
    };
}
Run Code Online (Sandbox Code Playgroud)

对于第二种情况。

粗略地说,这意味着,对于格式化程序,将分别调用(特征的){}函数来引用或。fmtDisplaythird*third

让我们应用这个逻辑

  • 第二种情况:third: &i32那么*third: i32,这就是impl Display for i32适用的地方。

  • 第一种情况:third: &i32,这也有效,因为impl<'_, T> Display for &'_ T(其中Ti32)

  • 最后一种情况: third: i32: 与第一种情况相同。此外,v[2](其类型为i32)之所以有效,是因为impl Index for Vec(请注意:let third = v[2]有效是因为impl Copy for i32,即应用复制语义=而不是默认的移动语义)。