何时应该使用引用而不是转移所有权?

21
Rust书籍所有权章节中得知,不可拷贝的值可以通过转移所有权或使用可变或不可变引用传递给函数。当你转移一个值的所有权时,它就不能在原始函数中使用了:如果你想要使用它,必须将其返回。当你传递一个引用时,你借用了这个值,并且仍然可以使用它。
我来自那些默认情况下数值是不可变的语言(如Haskell、Idris等)。因此,我可能从未考虑过使用引用。在两个地方有相同的值看起来很危险(或者至少很尴尬)。既然引用是一种特性,肯定有使用它们的理由。
有哪些情况下我应该强制自己使用引用?这些情况是什么,为什么它们有益?还是只是为了方便,传递所有权是可以的?

2
在同一时间,同一个值出现在两个地方看起来很混乱[...] 特别是可变的引用看起来非常危险。你使用过哪些其他编程语言?其中绝大部分都会在大多数时候隐式使用“可变引用”。你认为大多数语言都很危险吗? - Shepmaster
4
@Shepmaster,是的,就我个人而言,我会这样做。我来自一些默认不可变的语言(如Haskell、Idris等),因此我可能根本不会考虑使用引用。但引用是一种特性,所以一定有它的原因。因此,我的问题是:是否有情况下我应该强迫自己使用引用?这些情况是什么,为什么有益?或者它们只是方便使用,默认传递所有权是可以的? - MaiaVictor
1
@Stargateur,我编辑了这个问题,你觉得怎么样? - MaiaVictor
1
在两个地方具有相同值,我认为看起来很危险(或者至少很尴尬)。如果您在纯函数式编程语言中向两个不同的函数传递相同的值,编译器/解释器很可能只是通过内部的“按引用传递”(by reference)共享它,并且这仍然应该是安全的,因为该值是不可变的。您能更好地阐述在Rust中拥有多个不可变引用的担忧吗? - E net4
1
@E_net4 没有误解,我知道编译器不允许我改变一个带有活动引用的值。这很好。我明白了。我不是在问是否会出现错误,我是在问是否有很多引用会导致令人费解的编译器错误和痛苦的调试时间。一开始看起来所有权转移更直接。但再次强调,我只是在问。你的语气似乎表明你很喜欢使用引用,所以我会尝试。经验会告诉我它们在实践中的表现如何。 - MaiaVictor
显示剩余6条评论
1个回答

19

可变引用看起来非常危险。

它们并不危险,因为 Rust 编译器不会让你做任何危险的事情。如果你有一个指向值的 &mut 引用,则不能同时拥有 任何 其他引用。

通常情况下,你应该传递引用。这样可以避免复制内存,并且应该是你默认的操作,除非你有充分的理由采取其他方式。

以下是一些转移所有权而不是传递引用的好理由:

  1. 当值的类型很小,例如 boolu32 等时,将这些值移动/复制以避免一级间接寻址通常会获得更好的性能表现。通常这些值实现了 Copy,实际上编译器可能会自动为您进行这种优化。这是因为 Rust 的强类型系统和默认不可变性质使得这种优化是免费的!
  2. 当值的当前所有者即将超出其作用域范围时,您可能希望将值移动到其他位置以保持其存活。

2
我的理解是,传递所有权不会复制任何内存。我认为这应该是默认设置。这个理解有误吗? - MaiaVictor
1
您可以将代码的行为视为值在内存中移动,实际上编译器可能会或可能不会真正移动它。 - Peter Hall
2
好的,谢谢你的意见。我的印象是使用引用会使我的值同时存在于太多地方,这将使得调试和推理自己的代码比如果我只有一个地方拥有它们时更加痛苦(即,传递所有权)。不过,作为更有经验的 Rust 开发者,我会采纳你的建议,并尝试使用引用。 - MaiaVictor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接