Rust可以通过Rc
非常优雅地处理引用计数。似乎社区的许多成员更喜欢使用语言的所有权/借用语义而不是使用Rc。这样编写的程序更简单,但除了循环引用之外,是否有必要呢?
显然,在跨线程方面,情况变得更加复杂。因此,为了简化我试图学习的内容,"在单线程应用程序中,除了作为编写时优化之外,是否需要引用计数?" 这是否是高级Rust技能的反模式?
Rust可以通过Rc
非常优雅地处理引用计数。似乎社区的许多成员更喜欢使用语言的所有权/借用语义而不是使用Rc。这样编写的程序更简单,但除了循环引用之外,是否有必要呢?
显然,在跨线程方面,情况变得更加复杂。因此,为了简化我试图学习的内容,"在单线程应用程序中,除了作为编写时优化之外,是否需要引用计数?" 这是否是高级Rust技能的反模式?
Rc
的例子是过滤具有“繁重”数据的查询,将其缩小到多个所有者。 基本上,每当您处理进入多个其他过滤集的“集合”时,其中过滤器可能重叠时。例如,如果您收集了1000张图像,并调用OpenCV(或类似软件)来查找原始集合中哪些图像具有鸟类,哪些图像中有树木,结果集可能会重叠。 因此,如果您不使用Rc
(或类似技术),则要么复制这些潜在巨大的图像(可能不需要),要么保留对它们的引用。好吧,但是然后您就无法释放原始图像集,因为它拥有结果集所引用的图像。虽然有解决方法(仅在一个或多个过滤条件说要这样做时保存图像),但由于使用的内存模型,这会导致深度整合程序的潜在分离部分。或者只需使用Rc
,其他人可以轻松地“访问”它,带入的任何东西都可以被“完成”,并且释放未引用的所有内容,同时仍保留仍在使用的集合部分。Rc
及相关技术可能会被过度使用。 我在C++中遇到这种情况的次数太多了,人们到处扔shared_ptr
并认为这时它们就“好”了(直到应用程序或DLL关闭,并且开始出现“为什么我的应用程序总是在退出时崩溃?”的请求)。 也就是说,即使是单线程,有时也需要共享所有权,以便可以将其传递给未知数量的消费者以备后用。与大多数工具一样,有解决某些问题的方法,但这可能会带来更多的痛苦。Rc
。使用 Arc
没有什么不同,但是它可能更常见,因为标准线程机制(如 std::thread::spawn
)需要所有权。Rc
。在这种情况下,您不能使用基本引用。您可以将类似于图形的关系标准化表示,并使用索引或 ID 代替引用,但这可能并不总是可行或可取。当然,如果您在可以以分层方式表示结构的情况下使用 Rc
,则使用 Rc
将是不必要的。'static
。在这些情况下,移动、clone()
或共享(使用 Rc
)是解决方案。Rc
本身就是反模式,它只是另一个工具,但有时可以避免使用它,从而得到更清晰的关系和/或更好的性能。我经常看到 Rust 新手慷慨地使用 Rc
,他们还没有完全掌握借用检查器。