我需要在几个使用闭包作为参数的函数之间传递资源.并且在这些数据中处理了数据,但它查找了变量实现的变化将反映在其余部分中.
我认为首先要使用的是Rc.我以前用过Arc处理不同线程之间的数据,但由于这些函数没有在不同的线程中运行,我选择了Rc.
我有最简化的代码,以表达我的疑虑:
使用RefCell是因为我可能必须看到这种语法不会像我预期的那样工作:
*Rc::make_mut(&mut rc_pref_temp)...
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
代码被简化,使用它的场景完全不同.我注意到这一点,以避免像"你可以为函数提供一个值"这样的评论,因为我感兴趣的是知道为什么暴露的案例以这种方式工作.
标准输出:
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 }
Run Code Online (Sandbox Code Playgroud)
test()我是Rust的新手,所以我不知道这种疯狂的语法是否正确.
*((*Rc::make_mut(&mut rc_pref_temp)).name_test).get_mut() += 1;
Run Code Online (Sandbox Code Playgroud)
运行时,test()您可以看到以前的语法有效,因为它会增加值,但这种增加不会影响克隆.我希望通过使用*Rc::make_mut(& mut rc_pref_temp)...共享引用的克隆将反映相同的值.
Rc引用了同一个对象,为什么对象的更改不适用于其余的克隆?为什么这样工作?难道我做错了什么?注意:我使用RefCell是因为在某些测试中我认为也许我有事可做.
test2()我知道了作为工作用料Mutex有Rc,但我不知道这是正确的方式.我有多么的一些想法Mutex和Arc作品,但使用此语法之后:
*Rc::make_mut(&mut rc_pref_temp)...
Run Code Online (Sandbox Code Playgroud)
使用Mutexin test2(),我想知道是否Mutex不仅要负责更改数据,还要负责反映所有克隆引用的变化.
共享引用实际上是指向同一个对象吗?我想他们会这样做,但是上面的代码中没有使用的反映没有反映Mutex,我有一些疑问.
在使用之前,您需要阅读并理解您使用的功能的文档.Rc::make_mut说,强调我的:
对给定的引用可变引用
Rc.如果有其他
Rc或Weak指向相同值的指针,make_mut则将调用clone内部值以确保唯一所有权.这也称为写时克隆.另请参见
get_mut,这将失败而不是克隆.
因为你打电话,你有多个Rc指针.因此,当您调用时,将克隆内部值,并且指针现在将彼此取消关联:rc_pref.clone()make_mutRc
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
}
Run Code Online (Sandbox Code Playgroud)
有Mutex作品的版本,因为它完全不同.你不是在调用一个克隆内部值的函数.当然,Mutex当你没有线程时使用a是没有意义的.a的单线程等价物Mutex是...... RefCell!
老实说,我不知道你是怎么找到的Rc::make_mut; 我以前从未听说过它.在对模块文件cell没有提到它,也不该模块文档rc.
我强烈建议您退后一步,重新阅读文档.该锈病编程语言的第二版有一个关于智能指针章,包括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
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
453 次 |
| 最近记录: |