Pointers 理解Box、ref和amp;及*

Pointers 理解Box、ref和amp;及*,pointers,rust,Pointers,Rust,我对指针在锈迹中的工作原理有点困惑。有ref,Box,&,*,我不确定它们是如何协同工作的 以下是我目前对它的理解: Box不是真正的指针-它是一种在堆上分配数据的方法,并在函数参数中传递未大小的类型(尤其是特性) ref用于模式匹配,借来匹配的东西,而不是拿走。比如说, let thing: Option<i32> = Some(4); match thing { None => println!("none!"), Some(ref x) => pri

我对指针在锈迹中的工作原理有点困惑。有
ref
Box
&
*
,我不确定它们是如何协同工作的

以下是我目前对它的理解:

  • Box
    不是真正的指针-它是一种在堆上分配数据的方法,并在函数参数中传递未大小的类型(尤其是特性)
  • ref
    用于模式匹配,借来匹配的东西,而不是拿走。比如说,

    let thing: Option<i32> = Some(4);
    match thing {
        None => println!("none!"),
        Some(ref x) => println!("{}", x), // x is a borrowed thing
    }
    println!("{}", x + 1); // wouldn't work without the ref since the block would have taken ownership of the data
    
    let thing:Option=Some(4);
    火柴{
    None=>println!(“None!”),
    Some(ref x)=>println!(“{}”,x),//x是借来的东西
    }
    普林顿!(“{}”,x+1);//如果没有ref,将无法工作,因为块将拥有数据的所有权
    
  • &
    用于生成借用(借用指针)。如果我有一个函数
    fn foo(&self)
    ,那么我将引用我自己,该引用将在函数终止后过期,而不使用调用方的数据。我还可以通过执行
    bar(&mydata)
    来传递我想要保留所有权的数据

  • *
    用于生成原始指针:例如,
    让y:i32=4;设x=&y为*const i32
    。我理解C/C++中的指针,但我不确定它如何与Rust的类型系统一起工作,以及如何安全地使用它们。我也不确定这种指针的用例是什么。此外,
    *
    符号可用于取消对事物的引用(什么事物,为什么?)

  • 有人能给我解释一下第四种类型的指针,并验证我对其他类型的理解是正确的吗?如果有人能指出我没有提到的任何常见用例,我将不胜感激。

    引用和原始指针在实现级别是一样的。从程序员的角度来看,不同之处在于引用是安全的(用生锈的术语来说),而原始指针则不是

    借用检查器保证引用始终有效(生命周期管理),一次只能有一个可变引用,等等

    这些类型的约束对于许多用例来说可能过于严格,因此原始指针(没有任何约束,如在C/C++中)对于实现低级数据结构和一般低级内容非常有用。但是,您只能在
    不安全的
    块中取消对原始指针的引用或对其执行操作

    标准库中的容器也使用原始指针、
    Box
    Rc
    实现


    <> >代码> box >代码>代码> RC <代码>是C++中的智能指针,即原始指针周围的包装。 >代码> box < /COD>在逻辑指针上是一个新类型(<代码> *const t< /COD>)。但是,它在构建和销毁期间分配和释放数据,因此不必从其他来源借用数据

    其他指针类型也是如此,比如
    Rc
    ——引用计数指针。这些是包含私有原始指针的结构,它们将这些指针分配到其中并从中取消分配

    原始指针的布局与普通指针完全相同,因此在某些情况下与C指针不兼容。重要的是,
    *const str
    *const[T]
    是胖指针,这意味着它们包含有关值长度的额外信息

    然而,原始指针绝对不能保证其有效性。例如,我可以安全地做

    123 as *const String
    
    此指针无效,因为内存位置
    123
    未指向有效的
    字符串。因此,当取消引用一个时,需要一个
    不安全的

    此外,尽管借用必须遵守某些规则,即如果一个借用是可变的,则不能有多个借用,但原始指针不必遵守这一点。但你不太可能与这些发生冲突


    *mut
    *const
    之间没有逻辑上的区别,尽管它们可能需要转换到另一个来执行某些操作-这种区别是文档性的。

    首先,您列出的所有项目实际上都是不同的,即使它们与指针相关<代码>框
    是库定义的智能指针类型
    ref
    是模式匹配的语法
    &
    是一个引用运算符,在引用类型中兼作sigil
    *
    是一个解引用运算符,在原始指针类型中兼作符号。请参阅下面的详细说明

    Rust中有四种基本指针类型,可分为两组-引用指针和原始指针:

    &T        - immutable (shared) reference
    &mut T    - mutable (exclusive) reference
    
    *const T  - immutable raw pointer
    *mut T    - mutable raw pointer
    
    最后两个之间的差别非常小,因为其中一个可以不受任何限制地转换到另一个,因此
    const
    /
    mut
    的区别主要是作为一个lint。可以自由创建指向任何对象的原始指针,例如,它们也可以从整数中凭空创建

    当然,引用的情况并非如此——引用类型及其交互定义了Rust的一个关键特性:借用。引用在如何创建和何时创建、如何使用以及如何相互交互方面有很多限制。作为回报,它们可以在没有
    不安全
    块的情况下使用。然而,借款究竟是什么以及它是如何运作的超出了这个答案的范围

    可以使用
    &
    运算符创建引用和原始指针:

    let x: u32 = 12;
    
    let ref1: &u32 = &x;
    let raw1: *const u32 = &x;
    
    let ref2: &mut u32 = &mut x;
    let raw2: *mut u32 = &mut x;
    
    引用和原始指针都可以使用
    *
    运算符取消引用,但对于原始指针,它需要
    不安全的
    块:

    *ref1; *ref2;
    
    unsafe { *raw1; *raw2; }
    
    解引用运算符通常被省略,因为另一个运算符“点”运算符(即,
    )会自动引用或解引用其左参数。例如,如果我们有这些定义:

    struct X { n: u32 };
    
    impl X {
        fn method(&self) -> u32 { self.n }
    }
    
    然后,尽管
    method()
    引用了
    self
    let x = X { n: 12 };
    let n = x.method();
    
    let x: Box<u32> = Box::new(12);
    let y: &u32 = &*x;
    
    let x: u32 = 12;
    
    let y = x;           // y: u32, a copy of x
    let ref z = x;       // z: &u32, points to x
    let ref mut zz = x;  // zz: &mut u32, points to x
    
    let z = &x;
    let zz = &mut x;
    
    let x: Option<Vec<u32>> = ...;
    
    match x {
        Some(ref v) => ...
        None => ...
    }
    
    match x {
        Some(v) => ...
        None => ...
    }