【问题标题】:How are Rust's Arc and Rc types different from having garbage collection?Rust 的 Arc 和 Rc 类型与垃圾回收有何不同?
【发布时间】:2014-12-26 21:23:41
【问题描述】:

The Rust Programming Language, first edition 说 Rust 没有垃圾收集器:

它在没有垃圾收集器的情况下维持这些目标

但是,在discussing choosing your guarantees 中还说:

Rc<T> 是一个引用计数指针。换句话说,这让我们拥有多个指向同一数据的“拥有”指针,并且当所有指针超出范围时,数据将被删除(将运行析构函数)。

据我了解,这正是指针在像 Python 这样的垃圾收集语言中的工作方式。

我认为垃圾收集是任何不需要手动释放动态分配内存的过程。但是,我想我不明白 Rust 指南认为垃圾收集是什么。

【问题讨论】:

  • 您的定义将“垃圾收集”本身与“自动内存管理”混为一谈。自动内存管理可以指代任何数量的非手动内存管理方法。垃圾回收就是这样一种方法:en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29
  • 据我所知,关于引用计数是否算作垃圾收集的一种形式,从来没有真正达成过共识。即使是这样,它也与其他形式如此不同,以至于比较没有用。如果您将标准库中可选的 RAII 驱动的引用计数智能指针视为 Rust 被垃圾收集,那么 C++ 也被垃圾收集。
  • 这是大多数情况下在 Python 中指针的工作方式。除了引用计数,Python 还有一个用于引用循环的后备 GC。有关参考周期的更多信息:Geeks for geeks.

标签: pointers garbage-collection rust


【解决方案1】:

我认为垃圾收集是任何不需要手动释放动态分配内存的过程

那么 Rust 确实有“垃圾收集”!

fn make_stuff() {
    // Allocate memory on the heap and store `true` in it
    let thing = Box::new(true);
    // Allocate memory on the heap and store 1000 numbers in it.
    let things = vec![42; 1000];
} // Look Ma! No manual deallocation!

thingthings 超出范围时(在本例中,在方法结束时),它们分配的内存将为您释放。

RcArc 允许比这更大的灵活性;您应该阅读their docs 以了解更多信息。


除了@Manishearth 的回答,还有这个细节(强调我的):

在其最后一个所有者的生命周期结束时自动释放

在许多垃圾收集语言中,垃圾收集与您的其余代码一起发生在带外。在 Rust 中,释放的位置是已知的。

鉴于这个 Java:

public static ArrayList alpha()
{
    return new ArrayList();
}

public static void beta()
{
    alpha(); // Unused result
}

我不相信您可以肯定地说 ArrayList 将从内存中删除。在等效的 Rust 代码中,您知道 ArcRc 一旦超出范围就会被破坏。

【讨论】:

    【解决方案2】:

    This 的文章有点老了,关于 Rust 现在发生了怎样的变化,但它强调了 Rust 没有 GC 意味着什么。只有 RAII 和所有权是 Rust 固有的。它们有助于编写类似于引用计数的 GC,例如 Rc 和 Arc,但它们不是语言的一部分,它们是标准库的一部分。它会产生巨大的影响。

    如果您考虑使用 Rust 编写操作系统,则不能在部分代码中使用任何形式的 GC 或使用标准库。在这个级别,重要的是要知道什么是语言的一部分,什么不是。举个简单的例子,看看here

    相比之下,在 Java 或 Python 等语言中,您无法阻止代码使用 GC,因为它通过语言设计隐式使用它。

    在 Rust 中,就像在 C/C++ 中一样,GC 是库的一部分,它的使用是明确的。

    【讨论】:

      【解决方案3】:

      Rc 没有循环收集。如果您创建一个引用循环,您可能会在程序尝试增加引用计数时崩溃。

      虽然这在技术上也算作垃圾收集器,但它并不是一个普遍有用的垃圾收集器,因为它可以包含的类型受到限制。

      【讨论】:

      • 你能澄清一下“你对它可以包含的类型有限制”的意思吗?
      • @MikeVella 我不能有循环引用。没有内置限制,但这是您应该遵循的。
      • 我的理解是reference counting is a form of garbage collection,因此Rc/Arc 不处理循环这一事实不会自动取消它作为垃圾收集器的资格。
      • @Shepmaster 是的,我在答案中提到了这一点,但是当人们问 Rust 是否有 GC 时,他们的意思是循环收集 GC。这是误导,因此我们只是说 Rust 没有 GC。引用计数 GC 也很容易在树外实现,因此成本低(因此您可以说所有带有指针的面向对象语言都有引用计数 GC),但是一个好的循环收集 GC 通常需要与运行时和所有集成实现起来并不简单——当人们要求 GC 时,这就是他们所要求的。
      • @DavidRoundy 不,您可以使用RcRefCell 创建循环。
      【解决方案4】:

      如果你坚持正确,垃圾收集器就会收集。它收集要释放的内存位置列表。另一方面,Rc/Arc 没有,所以我认为你不能称之为垃圾收集。

      然而 rust 有 std::gc 模块,所以是的 rust 实际上现在有一个可选的垃圾收集器。

      【讨论】:

      • std::gc 在 0.11 和 0.12 版本之间是 removed
      • 而 IIRC,Gc 从未正确实施,只是伪装的 Rc
      猜你喜欢
      • 2021-06-12
      • 1970-01-01
      • 2015-12-17
      • 2015-11-13
      • 2012-12-23
      • 2011-08-01
      • 2012-02-19
      • 2015-12-27
      • 1970-01-01
      相关资源
      最近更新 更多