我需要在几个使用闭包作为参数的函数之间传递资源。在这些数据中,数据得到了处理,但它寻找的变量将反映在变量中。
我认为首先要使用Rc
。我之前使用Arc
来处理不同线程之间的数据,但由于这些函数不在不同的线程中运行,我选择了Rc
。
我所拥有的最简化的代码,以表达我的疑虑:
RefCell
的使用是因为我可能必须看到这种语法不能像我预期的那样工作:
*Rc::make_mut(&mut rc_pref_temp)...
use std::sync::Arc;
use std::rc::Rc;
use std::sync::Mutex;
use std::cell::RefCell;
use std::cell::Cell;
fn main() {
test2();
println!("---");
test();
}
#[derive(Debug, Clone)]
struct Prefe {
name_test: RefCell<u64>,
}
impl Prefe {
fn new() -> Prefe {
Prefe {
name_test: RefCell::new(3 as u64),
}
}
}
fn test2(){
let mut prefe: Prefe = Prefe::new();
let mut rc_pref = Rc::new(Mutex::new(prefe));
println!("rc_pref Mutex: {:?}", rc_pref.lock().unwrap().name_test);
let mut rc_pref_temp = rc_pref.clone();
*rc_pref_temp.lock().unwrap().name_test.get_mut() += 1;
println!("rc_pref_clone Mutex: {:?}", rc_pref_temp.lock().unwrap().name_test);
*rc_pref_temp.lock().unwrap().name_test.get_mut() += 1;
println!("rc_pref_clone Mutex: {:?}", rc_pref_temp.lock().unwrap().name_test);
println!("rc_pref Mutex: {:?}", rc_pref.lock().unwrap().name_test);
}
fn test(){
let mut prefe: Prefe = Prefe::new();
let mut rc_pref = Rc::new(prefe);
println!("rc_pref: {:?}", rc_pref.name_test);
let mut rc_pref_temp = rc_pref.clone();
*((*Rc::make_mut(&mut rc_pref_temp)).name_test).get_mut() += 1;
println!("rc_pref_clone: {:?}", rc_pref_temp.name_test);
*((*Rc::make_mut(&mut rc_pref_temp)).name_test).get_mut() += 1;
println!("rc_pref_clone: {:?}", rc_pref_temp.name_test);
println!("rc_pref: {:?}", rc_pref.name_test);
}
代码被简化,使用它的场景完全不同。我注意到这一点,以避免像#34;你可以为函数&#34;提供一个值,因为我感兴趣的是知道为什么暴露的案例以这种方式工作。
标准输出:
rc_pref Mutex : RefCell { value: 3 }
rc_pref_clone Mutex : RefCell { value: 4 }
rc_pref_clone Mutex : RefCell { value: 5 }
rc_pref Mutex : RefCell { value: 5 }
---
rc_pref : RefCell { value: 3 }
rc_pref_clone : RefCell { value: 4 }
rc_pref_clone : RefCell { value: 5 }
rc_pref : RefCell { value: 3 }
test()
我是Rust的新手,所以我不知道这种疯狂的语法是否正确。
*((*Rc::make_mut(&mut rc_pref_temp)).name_test).get_mut() += 1;
运行test()
时,您可以看到之前的语法有效,因为它会增加值,但这种增加不会影响克隆。我希望通过使用*Rc::make_mut(& mut rc_pref_temp)...
,共享引用的克隆将反映相同的值。
Rc
引用了同一个对象,为什么对象的更改不适用于其他克隆?为什么这样工作?我做错了吗?注意:我使用RefCell
因为在某些测试中我认为我可能有事情要做。
test2()
我使用Mutex
使用Rc
按预期工作,但我不知道这是否正确。我对Mutex
和Arc
的工作原理有一些想法,但在使用此语法之后:
*Rc::make_mut(&mut rc_pref_temp)...
在Mutex
中使用test2()
,我想知道Mutex
是否不仅负责更改数据,而且负责反映所有克隆的数据引用。
共享引用实际上指向同一个对象吗?我想他们会这么做,但是如果没有使用Mutex
而没有反映出更改的上述代码,我有一些疑问。
答案 0 :(得分:6)
在使用之前,您需要阅读并理解您使用的功能的文档。 Rc::make_mut
says,强调我的:
对给定的
Rc
进行可变引用。如果有其他
Rc
或Weak
指针指向相同的值,那么make_mut
将在内部值上调用clone
以确保唯一 所有权。这也称为写在克隆。另请参阅
get_mut
,它将失败而不是克隆。
您有多个Rc
指针,因为您调用了rc_pref.clone()
。因此,当您调用make_mut
时,内部值将被克隆,Rc
指针现在将彼此解除关联:
use std::rc::Rc;
fn main() {
let counter = Rc::new(100);
let mut counter_clone = counter.clone();
println!("{}", Rc::strong_count(&counter)); // 2
println!("{}", Rc::strong_count(&counter_clone)); // 2
*Rc::make_mut(&mut counter_clone) += 50;
println!("{}", Rc::strong_count(&counter)); // 1
println!("{}", Rc::strong_count(&counter_clone)); // 1
println!("{}", counter); // 100
println!("{}", counter_clone); // 150
}
Mutex
的版本有效,因为它完全不同。你不是在调用一个克隆内部值的函数。当然,当你没有线程时使用Mutex
是没有意义的。 Mutex
的单线程等价物是...... RefCell
!
老实说,我不知道你是怎么找到的Rc::make_mut
;我以前从未听过。 module documentation for cell
没有提到它,module documentation for rc
也没有提到它。
我强烈建议您退后一步,重新阅读文档。 second edition of The Rust Programming Language有一个chapter on smart pointers,包括Rc
和RefCell
。阅读rc
和cell
的模块级文档。
这是您的代码应该是什么样子。请注意borrow_mut
的使用情况。
fn main() {
let prefe = Rc::new(Prefe::new());
println!("prefe: {:?}", prefe.name_test); // 3
let prefe_clone = prefe.clone();
*prefe_clone.name_test.borrow_mut() += 1;
println!("prefe_clone: {:?}", prefe_clone.name_test); // 4
*prefe_clone.name_test.borrow_mut() += 1;
println!("prefe_clone: {:?}", prefe_clone.name_test); // 5
println!("prefe: {:?}", prefe.name_test); // 5
}