首页 文章

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

提问于
浏览
8

今天的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);
}

这看似合理 . 它打印"6",如果 sum_vecv 是C引用,这就是你所期望的;它只是一个内存位置的名称,我们在 main() 中定义了向量 v1 .

然后我用这个替换了 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);
}

type [i32] cannot be dereferenced . 哦,感谢上帝,这是有道理的 . 但我原本预计会有两次迭代!

Rust中的引用不是C "names for another place in memory,"但它们是什么?它们也不是指针,关于它们的规则似乎要么是深奥的,要么是高度特殊的 . 发生了什么,这样一个引用,一个指针和一个指向指针的指针在这里同样运作良好?

1 回答

  • 9

    规则不是临时的,也不是真正的深奥 . 检查 v 的类型,它有各种解除引用:

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

    你会得到:

    • v - > &std::vec::Vec<i32>

    • *v - > std::vec::Vec<i32>

    • **v - > [i32]

    您已经理解的第一个解引用 . 第二个取消引用归功于Deref特征 . Vec<T>[T] 的引用 .

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

    • 如果类型具有方法,请使用它并退出查找 .

    • 如果对该类型的引用具有该方法,请使用它并退出查找 .

    • 如果可以取消引用类型,请执行此操作,然后返回步骤1 .

    • 否则查找失败 .

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

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

相关问题