我是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
任何评论都会受到很多赞赏。谢谢。
您可以将T
和Box<T>
之间的区别视为静态分配的对象和动态分配的对象(后者通过C ++术语中的new
表达式创建)之间的差异。
在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 ++非常相似,这意味着对象没有单个所有者,并且该对象将由指向它的最后一个引用计数包装器处理。
您链接的文章使用过时的语法。某些智能指针曾经有过特殊的名称和相关的语法,自Rust 1.0之前的一段时间以来已被删除:
Box<T>
取代了~T
(“拥有指针”)Rc<T>
取代了@T
(“管理指针”)由于Internet永远不会忘记,您仍然可以找到使用旧语法的1.0之前的文档和文章(例如您链接的文档)。检查文章的日期:如果是在2015年5月之前,你正在处理一个早期的,不稳定的Rust。