在Rust中,引用如何成为指向指针的指针?

时间:2017-04-05 17:10:33

标签: rust

今天的Rust之谜来自The Rust Programming Language,第一版的第4.9节。引用和借用的例子有这个例子:

fn main() {
    fn sum_vec(v: &Vec<i32>) -> i32 {
        return v.iter().fold(0, |a, &b| a + b);
    }

    fn foo(v1: &Vec<i32>) -> i32 {
        sum_vec(v1);
    }

    let v1 = vec![1, 2, 3];

    let answer = foo(&v1);
    println!("{}", answer);
}

这似乎很合理。它打印&#34; 6&#34;,这是你期望的 v的{​​{1}}是C ++参考;它只是一个记忆的名字 location,我们在sum_vec中定义的向量v1

然后我将main()的主体替换为:

sum_vec

它按预期编译和工作。好吧,那不是......完全疯了。编译器试图让我的生活更轻松,我明白了。令人困惑的是,我必须记住这些语言的特定时态,但并非完全疯狂。然后我试了一下:

fn sum_vec(v: &Vec<i32>) -> i32 {
    return (*v).iter().fold(0, |a, &b| a + b);
}

它仍然有效!怎么了?

fn sum_vec(v: &Vec<i32>) -> i32 {
    return (**v).iter().fold(0, |a, &b| a + b);
}

fn sum_vec(v: &Vec<i32>) -> i32 { return (***v).iter().fold(0, |a, &b| a + b); } 。哦,感谢上帝,这是有道理的。但我原本预计会有两次迭代!

Rust中的引用不是C ++&#34;内存中另一个地方的名称,&#34;但 是什么?它们也不是指针,关于它们的规则似乎是深奥的或高度特殊的。发生了什么,这样一个引用,一个指针和一个指向指针的指针在这里同样运作良好?

1 个答案:

答案 0 :(得分:9)

规则不是 ad-hoc ,也不是真正的深奥。检查v的类型及其各种解除引用:

fn sum_vec(v: &Vec<i32>) {
    let () = v;
}

你会得到:

  1. v - &gt; &std::vec::Vec<i32>
  2. *v - &gt; std::vec::Vec<i32>
  3. **v - &gt; [i32]
  4. 您已经了解的第一个解引用。第二个取消引用归功于Deref特征。 Vec<T> [T] var string = &lt;p&gt;It&#39;s a round about way.&lt;/p&gt; &lt;p&gt;&lt;!-- pagebreak --&gt;But Maybe this is the way?&lt;/p&gt;; 的解除引用。

    执行方法查找时,there's a straight-forward set of rules

    1. 如果类型包含方法,请使用它并退出查找。
    2. 如果对该类型的引用具有该方法,请使用它并退出查找。
    3. 如果可以取消引用该类型,请执行此操作,然后返回步骤1.
    4. 否则查找失败。
    5.   

      Rust中的引用不是C ++“内存中另一个地方的名称”,

      它们绝对是记忆中某个地方的名字。实际上,它们会编译成你知道的相同的C / C ++指针。