Rust 理解借用和取消引用

Rust 理解借用和取消引用,rust,Rust,我在阅读锈迹文件,似乎不能完全理解正在发生的事情。例如,在上面,我看到以下示例: //此函数获取一个长方体的所有权并将其销毁 fn吃盒(盒装:盒){ println!(“销毁包含{}的盒子”,装箱为32); } //此函数借用了i32 fn借出(借出:&i32){ println!(“这个int是:{}”,借用了i32); } fn main(){ //创建装箱的i32和堆叠的i32 设boxed_i32=Box::new(5_i32); 设叠加的_i32=6_i32; //借用盒子里的东西。不

我在阅读锈迹文件,似乎不能完全理解正在发生的事情。例如,在上面,我看到以下示例:

//此函数获取一个长方体的所有权并将其销毁
fn吃盒(盒装:盒){
println!(“销毁包含{}的盒子”,装箱为32);
}
//此函数借用了i32
fn借出(借出:&i32){
println!(“这个int是:{}”,借用了i32);
}
fn main(){
//创建装箱的i32和堆叠的i32
设boxed_i32=Box::new(5_i32);
设叠加的_i32=6_i32;
//借用盒子里的东西。不获取所有权,
//因此,内容可以再次借用。
借用(已装箱的);
借用(和堆叠);
{
//引用框中包含的数据
让_ref_to_i32:&i32=&boxed_i32;
//错误!
//当内部值稍后在作用域中借用时,无法销毁'boxed_i32'。
吃盒子(盒装的);
//FIXME^注释掉这行
//内部值被销毁后,尝试借用“\u ref\u to\u i32”
借用i32(参考至i32);
//“_ref_to_i32”超出范围,不再被借用。
}
//‘boxed_i32’现在可以放弃对‘eat_box’的所有权并被销毁
吃盒子(盒装的);
}
我相信:

  • eat_box_i32获取指向盒子的指针
  • 此行
    let boxed_i32=Box::new(5_i32)
    makes使得boxed_i32现在包含一个指针,因为Box不是原语
  • 我不明白的事情:

  • 为什么我们需要调用
    borrow_i32(&boxed_i32)与符号?boxed_i32不是已经是指针了吗
  • 在这一行:
    let _ref_to_i32:&i32=&boxed_i32为什么右侧需要符号和?boxed_i32不是已经是地址了吗
  • 为什么可以使用指向Box的指针和指向i32的指针调用borrow_i32
  • 对“指针”一词的评论 如果您愿意,您可以跳过这一部分,我只是想,考虑到您提出的问题,这可能是一个有用的评论:

    在Rust中,
    &i32
    &mut i32
    *const i32
    *mut i32
    Box
    Rc
    Arc
    都可以说是“指向
    i32
    的指针”类型。然而,生锈不会让你随意地在它们之间转换,即使是在内存中相同排列的那些之间

    有时谈论指针是很有用的,但根据经验,如果你想弄清楚为什么一段代码可以编译,而另一段代码不能编译,我建议你跟踪使用哪种指针


    你相信的事情:
  • eat_box_i32获取指向盒子的指针
  • 其实不完全是
    eat\u box\u i32
    接受一个
    box
    ,而不是指向
    box
    的指针。恰好内存中的
    被存储为指向
    i32
    的指针

  • 这一行让boxed_i32=Box::new(5_i32);make是这样的,所以boxed_i32现在包含一个指针,因为Box不是原语
  • 是,
    boxed_i32
    是指针


    你不明白的事情:
  • 为什么我们需要调用借用(borrow_i32)(&boxed_i32);用符号?boxed_i32不是已经是指针了吗
  • 是,
    boxed_i32
    已经是指针。但是,装箱指针仍然表示所有权。如果您通过了<代码> BOXEDITI32 <代码>,而不是<代码>和BOXEDII32 >代码>,您仍然会传递一个指针,但是Road会考虑变量“被消耗”,并且在函数调用之后,您将不能再使用<代码> BxEdEdI32 < /代码>。
  • 在这一行上:让_ref_to_i32:&i32=&boxed_i32;为什么右手边需要使用符号和?boxed_i32不是已经是地址了吗
  • 是的,
    boxed_i32
    已经是一个地址,但它是一个地址这一事实有点不透明(就像一个带有单个私有字段的
    struct
    )。
    &Box的实际类型是
    &Box

    虽然这很奇怪,对吧?如果
    &boxed_i32
    &Box
    ,如何将其分配给
    &i32
    类型的变量

    这实际上是一种简写——如果类型
    T
    实现了
    Deref
    特性,它将根据需要自动将类型
    &T
    的值转换为类型
    &R
    的值。结果是,
    Box
    类型实现了
    Deref

    请参阅,以了解有关
    Deref
    的更多信息

    因此,如果您在没有自动转换的情况下显式地写出它,那么该行实际上看起来像:

    let _ref_to_i32: &i32 = Deref::deref(&boxed_i32);
    
  • 为什么可以使用指向Box的指针和指向i32的指针调用borrow_i32
  • 原因与上述(2)相同

    borrow\u i32
    接受
    &i32
    作为其参数。传递
    &i32
    显然是可以的,因为类型完全匹配。如果您尝试将其传递给
    &Box
    ,Rust会自动将其转换为
    &i32
    ,因为
    Box
    实现
    Deref


    编辑:感谢@kmdreko指出
    Deref
    允许强制,而不是
    AsRef