【问题标题】:Why does Clippy suggests passing an Arc as a reference?为什么 Clippy 建议传递 Arc 作为参考?
【发布时间】:2019-08-29 18:42:55
【问题描述】:

我正在检查我的代码中的 Clippy 发现,发现 the pedantic rule 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);
    }
}

Playground

【问题讨论】:

    标签: rust clean-architecture rust-clippy


    【解决方案1】:

    调用arc_taker(arc.clone()) 会增加引用计数,从arc_taker 返回会再次减少引用计数。在这种情况下这是没有用的,因为mainarc 变量已经在整个调用期间保持Arc 处于活动状态。对它的引用就足够了。无需增加和减少引用计数。

    在您的具体示例中,arc_taker 甚至不关心它是否由Arc 管理。它只关心Mutexlock,所以为了减少你的功能限制,只需使用&amp;Mutex&lt;MyStruct&gt;

    如果你想对它做任何Arc 特定的事情,比如获取weak_count 或其他东西,那么使用&amp;Arc&lt;..&gt; 是有意义的。如果您的函数将保留 Arc 的克隆,那么只有按值获取 Arc 才有意义,因为调用者可以决定通过调用 .clone() 来给您额外的引用(从而碰撞引用计数),或者给你它自己的Arc 的所有权(因此不会增加引用计数)。

    【讨论】:

    • 很好的答案。 FWIW,here's my version of the &amp;Mutex&lt;MyStruct&gt; solution.(当然,这使 arc_taker 成为一个坏名字,因为它不需要 Arc。)
    • 这里有一个普遍的基本原则可能一文不值:一个函数应该只做它正常工作所需的尽可能多的假设,这应该反映在它所采用的参数类型中.这与推荐使用&amp;str&amp;String 的原则相同。
    • @MatthieuM。是的,这是一个很好的补充。在这种特定情况下,这也意味着它甚至不应该采用&amp;Mutex,因为无论如何该函数总是将其锁定。它应该只需要一个&amp;MyStruct,并将锁定留给调用者。然后,已经为其他事情锁定互斥锁的调用者也可以调用该函数,而无需先解锁互斥锁。 (但我假设这个问题来自的原始代码不仅仅是.lock().something()。)
    • @AkinerAlkan 我想我不知道为什么你会认为这是一个 false positive 的clippy lint。 arc_taker 的主体不需要消耗Arc,因此可以重写以接受&amp;Arc。这就是 lint 所说的。您可以出于任何原因选择忽略它,但这不会使其 false.
    • @AkinerAlkan 打破这个原则意味着限制你的函数的使用方式。如果你的代码的其他部分有一个Rc&lt;Mutex&gt; 或只是一个Box&lt;Mutex&gt;,如果它不能使用你的函数,那就太可惜了,因为它不必要地需要一个Arc&lt;Mutex&gt;。如果您确实需要Arc,则在引用就足够时按值取值不仅意味着性能下降(两次写入原子),而且还会使界面不符合人体工程学:arc_taker(a) 会消耗 a,因此用户该函数需要调用.clone() 而不是只写&amp;a
    猜你喜欢
    • 2018-07-28
    • 2011-12-15
    • 2016-04-11
    • 2014-02-10
    • 1970-01-01
    • 2014-03-05
    • 2019-12-28
    • 2023-03-24
    • 2013-05-28
    相关资源
    最近更新 更多