我读了几本 articles我还不清楚。看起来 T
和 &T
可以互换,只要编译器不显示任何错误。但是在我阅读了official doc之后我想通过引用传递所有内容以利用借用。
当 T 是对象/字符串时,您能否提供任何关于将 arg 作为 T
传递给 &T
的简单规则?例如,在 C++ 中有 3 个选项:
T
– 复制值,不能改变当前值&T
– 不创建副本,可以改变当前值const &T
– 不创建副本,不能改变当前值
例如,如果我想在 T 超出我的 child 函数(我的函数将 T
传递给);并使用 &T
如果我想在只读模式下使用我的子函数,然后继续在我当前的(父)函数中使用它。
谢谢!
最佳答案
这些是我个人使用的规则(按顺序)。
按值传递 (
T
) 如果参数具有泛型类型并且此泛型类型实现的特征全部采用&self
或&mut self
但是对于impl
有一个毯子&T
或&mut T
(分别)用于实现该特征(或这些特征)的所有类型T
。例如,在std::io::Write
中,所有方法都采用&mut self
,但标准库提供了一个全面的实现impl<'a, W: Write + ?Sized> Write for &'a mut W
。这意味着尽管您按值接受T
(其中T: Write
),但可以传递&mut T
,因为&mut T
还实现了Write
。如果您必须获得该值的所有权(例如,因为您将它传递给另一个按值获取它的函数/方法,或者因为替代方案可能需要昂贵的克隆),则按值传递 (
T
)。如果您必须改变对象(通过调用其他通过可变引用获取对象的函数/方法,或者只是通过覆盖它并希望调用者看到新值),则通过可变引用 (
&mut T
) 传递但不需要取得它的所有权。如果类型是
T
并且很小(我对小的标准是Copy
,但其他人的标准可能略有不同),则按值 (size_of::<T>() <= size_of::<usize>() * 2
) 传递。原始整数和浮点类型是此类类型的示例。通过引用传递这些类型的值会在内存中创建一个不必要的间接寻址,因此调用者将不得不执行额外的机器指令来读取它。当size_of::<T>() <= size_of::<usize>()
时,您通常不会通过引用传递值来保存任何内容,因为T
和&T
通常会同时传递到一个寄存器中(如果函数的参数足够少)。否则通过共享引用 (
&T
) 传递。
一般来说,如果可能,更喜欢通过共享引用传递。当类型很大或管理内存以外的资源时,这可以避免潜在的昂贵克隆,并在调用后如何使用值方面为调用者提供最大的灵 active 。
E.g., is it a good idea to pass by
T
if I want to deallocateT
after it goes out of scope in my child function (the function I'm passingT
to)
你最好有一个很好的理由!如果您决定稍后在调用方中实际需要使用 T
,那么您将不得不更改被调用方的签名并更新所有调用站点(因为与 C++ 不同,从 T
到 const T&
大部分是透明的,从Rust 中的 T
到 &T
不是:您必须在所有调用站点的参数前面添加一个 &
。
如果您尚未使用 Clippy,我建议您使用它。 Clippy has a lint that can notify you if you write a function that takes an argument by value but the function doesn't need to take ownership of it(此 lint 默认情况下用于发出警告,但不再发出警告😞,因此您必须使用 #[warn(clippy::needless_pass_by_value)]
手动启用它)。
关于rust - 在 Rust 中处理传递参数时的经验法则是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54337061/