rust - 在 Rust 中处理传递参数时的经验法则是什么?

标签 rust

我读了几本 articles我还不清楚。看起来 T&T 可以互换,只要编译器不显示任何错误。但是在我阅读了official doc之后我想通过引用传递所有内容以利用借用。

当 T 是对象/字符串时,您能否提供任何关于将 arg 作为 T 传递给 &T 的简单规则?例如,在 C++ 中有 3 个选项:

  • T – 复制值,不能改变当前值
  • &T – 不创建副本,可以改变当前值
  • const &T – 不创建副本,不能改变当前值

例如,如果我想在 T 超出我的 child 函数(我的函数将 T 传递给);并使用 &T 如果我想在只读模式下使用我的子函数,然后继续在我当前的()函数中使用它。

谢谢!

最佳答案

这些是我个人使用的规则(按顺序)。

  1. 按值传递 (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

  2. 如果您必须获得该值的所有权(例如,因为您将它传递给另一个按值获取它的函数/方法,或者因为替代方案可能需要昂贵的克隆),则按值传递 ( T )。

  3. 如果您必须改变对象(通过调用其他通过可变引用获取对象的函数/方法,或者只是通过覆盖它并希望调用者看到新值),则通过可变引用 ( &mut T ) 传递但不需要取得它的所有权。

  4. 如果类型是 T 并且很小(我对小的标准是 Copy ,但其他人的标准可能略有不同),则按值 ( size_of::<T>() <= size_of::<usize>() * 2 ) 传递。原始整数和浮点类型是此类类型的示例。通过引用传递这些类型的值会在内存中创建一个不必要的间接寻址,因此调用者将不得不执行额外的机器指令来读取它。当 size_of::<T>() <= size_of::<usize>() 时,您通常不会通过引用传递值来保存任何内容,因为 T&T 通常会同时传递到一个寄存器中(如果函数的参数足够少)。

  5. 否则通过共享引用 (&T) 传递。

一般来说,如果可能,更喜欢通过共享引用传递。当类型很大或管理内存以外的资源时,这可以避免潜在的昂贵克隆,并在调用后如何使用值方面为调用者提供最大的灵 active 。

E.g., is it a good idea to pass by T if I want to deallocate T after it goes out of scope in my child function (the function I'm passing T to)

你最好有一个很好的理由!如果您决定稍后在调用方中实际需要使用 T,那么您将不得不更改被调用方的签名并更新所有调用站点(因为与 C++ 不同,从 Tconst 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/

相关文章:

generics - 在Rust中编写一个将可迭代容器作为参数的泛型函数

rust - Rust的确切自动引用规则是什么?

rust - 如何将生命周期设置为闭包中捕获的值?

intellij-idea - 如何自动修复 Rust 中未使用的导入?

arrays - 对数组进行切片或使用 Iterator::skip 哪个更有效?

rust - 派生特征会导致意外的编译器错误,但手动实现有效

windows - 流的Hello World程序编译导出不包含有效的UTF-8

syntax - 如何编写更通用的 IntoIter 函数

rust - 如何在 Rust 2018 中惯用地为箱子起别名?

rust - 如何从向量中克隆最后一个元素?