我是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
任何评论都会引起很多关注。谢谢。
答案 0 :(得分:3)
您可以将T
和Box<T>
之间的区别视为静态分配的对象和动态分配的对象(后者是通过new
表达式创建的)之间的区别。 C ++术语)。
在Rust中,T
和Box<T>
都代表对所引用对象具有所有权的变量(即,当变量超出范围时,该对象将被销毁(无论是按值存储还是按引用存储)。相反,&T
和&mut T
代表对象的借用(即,这些变量不负责破坏对象,并且它们的寿命不能超过对象的所有者)。
默认情况下,您可能希望使用T
,但有时您可能希望(或必须)使用Box<T>
。例如,如果您想拥有一个Box<T>
,而该{太大,则无法分配到位(例如在堆栈上),则可以使用T
。当对象完全没有已知大小时,也可以使用它,这意味着您存储或传递它的唯一选择是通过“指针”(Box<T>
)。
在Rust中,对象通常是可变的或别名的,但不能两者兼有。如果您给出了对某个对象的不可变引用,则通常需要等到这些引用结束后才能再次对该对象进行更改。
此外,Rust的不变性是可传递的。如果您一成不变地收到一个对象,则意味着您也可以一成不变地访问它的内容(以及那些内容的内容,等等)。
通常,所有这些操作都是在编译时强制执行的。这意味着您可以更快地捕获错误,但仅限于只能表达编译器可以静态证明的内容。
就像T
和Box<T>
一样,有时您可以使用RefCell<T>
,这是另一种所有权类型。但是与T
和Box<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。