【问题标题】:Is a `mut` on a moved function parameter leaking implementation details to the function's API?移动的函数参数上的“mut”是否会将实现细节泄露给函数的 API?
【发布时间】:2021-08-10 11:25:20
【问题描述】:

我是 Rust 新手,正在阅读 Rust 编程书的第二版。我想知道下面的问题,但到目前为止找不到答案。

定义函数时,可以移动一些参数。如果您打算在函数中改变它们,也可以声明它们 mut(不带引用)。

然而,对于调用者来说,这个mut 似乎没有任何意义。他们刚刚转移了所有权,在那之后数据会发生什么并不是他们关心的问题,不是吗?

那么,是否可以说 mut 以及移动的参数实际上不是函数 API 的一部分?相反,它会将该函数的实现细节泄露给它的签名。

感谢您帮助我更好地理解这一点。

问候, 亚历克斯

【问题讨论】:

  • 只想提一下,Rust 生成的文档在记录函数时不包括 mut。以Vecinto_boxed_slice(self) 为例,它在source 中使用mut self

标签: rust


【解决方案1】:

你说得对,mut 不会以任何方式改变界面。这两个函数的函数指针类型

fn foo(s: String);
fn bar(mut s: String);

is fn(String) - 绑定是否可变不是函数类型的一部分。由于无论有无 mut,这些类型都被认为是相同的,所以 mut 不是 API 的任何有意义的部分。

还要注意,一个函数可以改变它接收所有权的任何值,不管相应的参数是否标记为mut。如果你有一个不可变的变量绑定,你总是可以将它移动到一个可变的绑定中,例如

fn foo(s: String) {
    let mut s = s;
    s.push_str("glonk");
}

所以签名中的 mut 既不是 API 的一部分,也没有真正告诉你函数正在做什么。

【讨论】:

  • 关于“它接收所有权”的注意事项:该函数始终接收其参数的所有权。 &T&mut T 只是另一种类型。这意味着该示例可以扩展为fn foo(s: &str),其中函数获取&str 的所有权(这很容易做到,因为&TCopy)。如上例所示,该函数既可以在签名中执行fn foo(mut s: &str),也可以在正文中执行let mut s: &str = s
  • @user2722968 除非你定义你的函数为fn foo(ref s: String),在这种情况下调用者会传入一个String,但函数只能访问一个&String。我想这个问题的答案是“你为什么要那样做?”
  • 除非你将你的函数定义为fn foo(ref mut s: String),否则会迷惑大家
猜你喜欢
  • 2022-12-12
  • 1970-01-01
  • 2021-03-18
  • 1970-01-01
  • 1970-01-01
  • 2021-04-24
  • 1970-01-01
  • 1970-01-01
  • 2010-12-05
相关资源
最近更新 更多