为啥 Clippy 建议传递 Arc 作为参考?

Posted

技术标签:

【中文标题】为啥 Clippy 建议传递 Arc 作为参考?【英文标题】: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

【问题讨论】:

【参考方案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

以上是关于为啥 Clippy 建议传递 Arc 作为参考?的主要内容,如果未能解决你的问题,请参考以下文章

spring MVC 怎么获取前端传递的数组参数

C语言中,数组名作为函数参数,属于啥传递,为啥?

react 传参为啥使用箭头函数?

为啥St. Joan of Arc是圣女贞德?Arc是啥意思?

当需要一个形式参数直接改变对应实参的值时,该形式参数应说明为啥参数?

opencl核函数怎么传二维数组实参