为什么Clippy建议通过Arc作为参考?

Web*_*rix 6 rust clippy clean-architecture

我正在检查代码中的Clippy调查结果,发现学究规则needless_pass_by_value可能是假阳性。

它说:

警告:此参数按值传递,但未在函数主体中使用

帮助:考虑参考: &Arc<Mutex<MyStruct>>

由于克隆Arc只是参考计数,因此移动Arc并不是一个坏主意。在质量和性能方面,发送参考而不是价值真的有什么区别Arc吗?

#![warn(clippy::pedantic)]

use std::sync::{Arc, Mutex};

fn main() {
    let my_struct = MyStruct { value: 3 };
    let arc = Arc::new(Mutex::new(my_struct));

    arc_taker(arc.clone());
}

fn arc_taker(prm: Arc<Mutex<MyStruct>>) {
    prm.lock().unwrap().do_something();
}

struct MyStruct {
    value: i32,
}

impl MyStruct {
    fn do_something(&self) {
        println!("self.value: {}", self.value);
    }
}
Run Code Online (Sandbox Code Playgroud)

操场

M-o*_*-se 7

调用将arc_taker(arc.clone())增加引用计数,然后arc_taker再从减少计数返回。在这种情况下,这是没有用的,因为arc变量main已经Arc在整个调用过程中保持活动状态。引用它就足够了。无需增加参考计数。

在您的特定示例中,arc_taker甚至不必关心它是由进行管理的Arc。它关心的只是有一个Mutexto lock,因此要使您的功能不受限制,只需取一个&Mutex<MyStruct>

如果您想Arc对它做任何特定的事情,例如获取weak_count或之类的东西,那么取一个&Arc<..>就很有意义。如果您的函数可以保留Arc的克隆,那么只有Arc按值取值才有意义,因为调用者可以决定通过调用.clone()(从而增加引用计数)或给您自己的所有权Arc(因此不会增加引用计数)。

  • 这里有一个通用的基本原理可能毫无价值:一个函数应仅做出使其正常工作所需的尽可能多的假设,这应反映在所采用的参数类型中。这是导致推荐使用`&str`和`&String`的相同原理。 (5认同)
  • @AkinerAlkan违反该原则意味着限制使用功能的方式。如果代码的其他部分具有`Rc &lt;Mutex&gt;`或仅具有`Box &lt;Mutex&gt;`,则不能使用您的函数是很可惜的,因为它不必要地需要`Arc &lt;Mutex&gt;`。如果确实需要`Arc`,则在引用足以满足需要时按值对其进行取值不仅意味着性能下降(两次写入原子),而且使接口的工效性降低:`arc_taker(a)将消耗a,因此该函数的用户将需要调用.clone()而不是仅编写&a。 (4认同)
  • 好答案。FWIW,[这是我的&Mutex &lt;MyStruct&gt;解决方案的版本。](https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=d21aecae3dbfd7827c8c11f52a13d91a)坏名,因为它不需要`Arc`。) (3认同)
  • @AkinerAlkan我想我不知道为什么您会认为这对于短毛棉绒来说是“假阳性”。“ arc_taker”的主体不需要使用“ Arc”,因此可以将其重写为接受“&Arc”。这就是皮棉所说的。您可以出于任何原因选择忽略它,但这并不能使它* false *。 (2认同)