rust - 理解 Rust 中的智能指针
问题描述
我是 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
任何评论将不胜感激。谢谢。
解决方案
您可以将 aT
和 a之间Box<T>
的区别视为静态分配对象和动态分配对象之间的区别(后者是通过new
C++ 术语中的表达式创建的)。
在 Rust 中,T
和都Box<T>
表示对所指对象拥有所有权的变量(即,当变量超出范围时,该对象将被销毁,无论它是通过值存储还是通过引用存储)。反之,则&T
表示&mut T
借用对象(即这些变量不负责销毁对象,也不能比对象的所有者更长寿)。
默认情况下,您可能想要使用T
,但有时您可能想要(或必须)使用Box<T>
. 例如,Box<T>
如果您想拥有一个T
太大而无法就地分配的 a,您将使用 a。当对象根本没有已知大小时,您也可以使用它,这意味着您存储它或传递它的唯一选择是通过“指针”(Box<T>
)。
在 Rust 中,一个对象通常要么是可变的,要么是别名的,但不能两者兼而有之。如果你已经给出了一个对象的不可变引用,你通常需要等到这些引用结束之后才能再次改变那个对象。
此外,Rust 的不变性是可传递的。如果您以不可变的方式接收到一个对象,则意味着您也可以不可变地访问其内容(以及这些内容的内容等)。
通常,所有这些事情都是在编译时强制执行的。这意味着您可以更快地捕获错误,但您只能表达编译器可以静态证明的内容。
像T
and Box<T>
,您有时可能会使用RefCell<T>
,这是另一种所有权类型。但与T
and不同Box<T>
的是,在运行RefCell<T>
时而不是编译时执行借用检查规则,这意味着有时你可以用它做一些安全但不会通过编译器的静态借用检查器的事情。这方面的主要示例是获取对对象内部的可变引用,该对象被不可变地接收(根据 Rust 的静态强制规则,这将使整个内部不可变)。
类型Ref<T>
和分别是和RefMut<T>
的运行时检查等价物。&T
&mut T
(编辑:这整件事有点谎言。&mut
真正的意思是“唯一借用”和&
“非唯一借用”。某些类型,如互斥锁,可以是非唯一的,但仍然可以可变地借用,否则它们将毫无用处。 )
Rust 的所有权模型试图推动你编写在编译时知道对象生命周期的程序。这在某些情况下效果很好,但会使其他情况难以或无法表达。
Rc<T>
及其原子兄弟Arc<T>
是T
. 它们为您提供了所有权模型的替代方案。
当您想要使用和正确处置一个对象时,它们很有用,但在您编写代码时不容易(或不可能)确定哪个特定变量应该是该对象的所有者(因此应该小心处理它)。就像在 C++ 中一样,这意味着对象没有单一所有者,并且该对象将由指向它的最后一个引用计数包装器处理。
推荐阅读
- android - 如何以编程方式更改 android.support.design.widget.FloatingActionButton 颜色
- react-native - ScrollView 不允许滚动,除非子组件是 Button 或 Touchable
- javascript - 如何在我的 .cshtml 页面中调用 Vue 组件?
- reactjs - 无法正确反应关闭织物面板
- python-3.x - 在标记化时我遇到了这个错误
- angularjs - Angular:检测到变量更改时如何自动重新渲染?
- python - 在 Python 中将命名空间放入不同的 XML 标记中
- php - 获得产品可见性价值 - WooCommerce
- flutter - mobx 可观察数据能否在多个屏幕之间持久存在?
- android - 数据绑定 - MediatorLiveData 未在 Fragment 内触发