当前位置: 首页 > 知识库问答 >
问题:

Box、ref、,

马哲
2023-03-14

我对指针在锈迹中的工作原理有点困惑。有refBox

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

>

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

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


共有3个答案

阎慈
2023-03-14

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

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

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

标准库中的容器也是使用原始指针BoxRc实现的。

BoxRc是C中的智能指针,即围绕原始指针的包装器。

方航
2023-03-14

Box在逻辑上是一个围绕原始指针的新类型(*const T)。然而,它在构建和销毁期间分配和释放数据,因此不必从其他来源借用数据。

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

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

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

123 as *const String

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

此外,虽然借用必须遵守某些规则——即如果一个借用是可变的,则不能有多个借用——但原始指针不必遵守这一点。还有其他更弱的法律必须遵守,但你不太可能触犯这些法律。

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

纪秋月
2023-03-14

首先,您列出的所有项目都是不同的东西,即使它们与指针有关。Box是库定义的智能指针类型;ref是模式匹配的语法;

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()通过引用获取selfself. n会自动取消对它的引用,因此您不必键入(*self). n。当调用method()时会发生类似的事情:

let x = X { n: 12 };
let n = x.method();

在这里,编译器自动引用x.method()中的x,因此您不必编写(

倒数第二段代码还演示了特殊的

因此,引用是Rust中的主要指针类型,几乎应该一直使用。没有引用限制的原始指针应用于实现高级抽象的低级代码(集合、智能指针等)和FFI(与C库交互)。

Rust也有动态大小(或未大小)的类型。这些类型没有明确的静态已知大小,因此只能通过指针/引用使用。但是,只有指针是不够的——需要额外的信息,例如,切片的长度或指向trait对象的虚拟方法表的指针。这些信息“嵌入”到指向未大小类型的指针中,使这些指针“变胖”。

胖指针基本上是一种结构,它包含指向数据段的实际指针和一些附加信息(切片的长度、指向特征对象vtable的指针)。这里重要的是,如果你通过

<代码>框

考虑长方体的一个非常有用的方法是将它们视为常规值,但大小是固定的。也就是说,Box

Boxes(事实上,几乎所有其他智能指针都是如此,比如Rc)也可以借用:你可以得到一个

let x: Box<u32> = Box::new(12);
let y: &u32 = &*x;

在这方面,Boxes类似于内置指针-您可以使用取消引用运算符来访问它们的内容。这是可能的,因为Rust中的取消引用运算符是可重载的,并且它对大多数(如果不是全部)智能指针类型都是重载的。这允许轻松借用这些指针内容。

最后,ref只是模式中的一种语法,用于获取引用类型的变量,而不是值。例如:

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;

(这也会使它更加惯用),在某些情况下refs是必不可少的,例如,在将引用引入枚举变体时:

let x: Option<Vec<u32>> = ...;

match x {
    Some(ref v) => ...
    None => ...
}

在上面的示例中,x仅在整个match语句中借用,这允许在match之后使用x。如果我们这样写:

match x {
    Some(v) => ...
    None => ...
}

然后x将被这个匹配消耗,之后将变得不可用。

 类似资料:
  • gtk.Box类是一个抽象类,用于定义容器的功能,其中窗口小部件放置在矩形区域中。 gtk.HBox和gtk.VBox小部件都是从它派生的。 gtk.Hbox中的子窗口小部件水平排列在同一行中。 另一方面,gtk.VBox的子窗口小部件垂直排列在同一列中。 gtk.Box类使用以下构造函数 - gtk.Box(homogenous = True, spacing = 0) homogenous属

  • Box

    长方体是三维或实心形状。 长方体由6个矩形制成,它们以直角放置。 使用方形面的长方体是一个立方体,如果面是矩形,而不是立方体,它看起来像一个鞋盒。 长方体是三维形状,具有length (深度), width和height ,如下图所示 - 在JavaFX中,三维框由名为Box的类表示。 该类属于包javafx.scene.shape 。 通过实例化此类,您可以在JavaFX中创建Box节点。 这个

  • Box

    「Box」是 Hexo 用来处理特定文件夹中的文件的容器,在 Hexo 中有两个 Box,分别是 hexo.source 和 hexo.theme,前者用于处理 source 文件夹,而后者用于处理主题文件夹。 载入文件 Box 提供了两种方法来载入文件:process, watch,前者用于载入文件夹内的所有文件;而后者除了执行 process 以外,还会继续监视文件变动。 box.proces

  • Box

    Box 是一种专门设计用于简化矢量图形的语言,另外还有一个集成的开发环境,该环境通过交互显示图形输出来促进该语言的使用。Box结合了使用鼠标绘制图形的便利性和使用针对矢量图形量身定制的语言描述图形的便利性。 特性 具有自动边界框计算功能,另存为PNG,PDF,SVG,PS GUI编辑脚本并查看结果

  • 了解如何在Java编程中使用PDF Box。 以下是示例 - 如何使用Java创建一个空的PDF文档。 如何使用Java将页面添加到PDF文档。 如何使用Java从PDF文档中删除页面。 如何使用Java向PDF添加文本。 如何使用Java在PDF中插入图像。 如何使用Java将PDF拆分为多个。 如何使用Java合并两个PDF。 如何使用java从PDF中提取图像。

  • 问题内容: 我想为标签。 对于 Mozila Firefox, 我尝试过 对于 IE(Internet Explorer), 我已经尝试了以下两种方法 但它不能在 IE(Internet Explorer)中工作 。虽然我已经申请 了 Internet Explorer, 但它在元素的宽度中添加了边框和填充。为什么会发生? 应该是什么问题?请帮助并向我求婚。 注意: 我使用的是 Internet