了解Rust中的智能指针

时间:2019-03-09 08:33:30

标签: rust smart-pointers

我是Rust的新手,并且写作以了解Rust中的“智能指针”。我对智能指针在C ++中的工作方式有基本的了解,并且自几年前以来就一直将其用于内存管理。但是令我非常惊讶的是,Rust还明确地提供了这样的实用程序。

由于此处的教程(https://pcwalton.github.io/2013/03/18/an-overview-of-memory-management-in-rust.html),似乎每个原始指针都已自动封装了一个智能指针,这似乎非常合理。那为什么我们仍然需要Box<T>Rc<T>Ref<T>这样的东西呢?根据此规范:https://doc.rust-lang.org/book/ch15-00-smart-pointers.html

任何评论都会引起很多关注。谢谢。

2 个答案:

答案 0 :(得分:3)

您可以将TBox<T>之间的区别视为静态分配的对象和动态分配的对象(后者是通过new表达式创建的)之间的区别。 C ++术语)。

在Rust中,TBox<T>都代表对所引用对象具有所有权的变量(即,当变量超出范围时,该对象将被销毁(无论是按值存储还是按引用存储)。相反,&T&mut T代表对象的借用(即,这些变量不负责破坏对象,并且它们的寿命不能超过对象的所有者)。

默认情况下,您可能希望使用T,但有时您可能希望(或必须)使用Box<T>。例如,如果您想拥有一个Box<T>,而该{太大,则无法分配到位(例如在堆栈上),则可以使用T。当对象完全没有已知大小时,也可以使用它,这意味着您存储或传递它的唯一选择是通过“指针”(Box<T>)。


在Rust中,对象通常是可变的或别名的,但不能两者兼有。如果您给出了对某个对象的不可变引用,则通常需要等到这些引用结束后才能再次对该对象进行更改。

此外,Rust的不变性是可传递的。如果您一成不变地收到一个对象,则意味着您也可以一成不变地访问它的内容(以及那些内容的内容,等等)。

通常,所有这些操作都是在编译时强制执行的。这意味着您可以更快地捕获错误,但仅限于只能表达编译器可以静态证明的内容。

就像TBox<T>一样,有时您可以使用RefCell<T>,这是另一种所有权类型。但是与TBox<T>不同的是,RefCell<T>在运行时强制执行借位检查规则 而不是编译时,这意味着有时您可以使用它来做安全,但不会通过编译器的静态借阅检查器。主要的例子是获取一个可变的对象内部的可变引用,该对象的内部是不可变的(在Rust的静态强制规则下,它将使整个内部不可变)。

类型Ref<T>RefMut<T>分别是&T&mut T的运行时检查等效项。


Rust的所有权模型试图促使您编写程序,其中在编译时知道对象的生存期。这在某些情况下效果很好,但使其他情况难以表达或无法表达。

Rc<T>及其原子同级Arc<T>T的引用计数包装器。他们为您提供了所有权模型的替代方法。

当您要使用和正确放置对象时,它们很有用,但是要确定(该对象的所有者)特定变量应为该对象的所有者(因此应谨慎处理)并不容易(或不可能)。就像在C ++中一样,这意味着该对象没有特定的所有者,并且该对象将由指向该对象的最后一个引用计数包装器处理。

答案 1 :(得分:2)

您链接的文章使用了过时的语法。某些智能指针曾经具有特殊的名称和相关的语法,自Rust 1.0之前的一段时间以来已被删除:

  • Box<T>替换为~T(“拥有的指针”)
  • Rc<T>替换为@T(“托管指针”)

由于Internet永远不会忘记,您仍然可以找到使用旧语法的1.0之前的文档和文章(例如,链接的文章)。检查文章的日期:如果是2015年5月之前,那么您正在处理早期的,不稳定的Rust。