作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我需要创建一个 Vec 来跟踪我正在创建的对象并更改它的状态以供以后使用。但是如果我在获取存储在 vec 上的对象时使用克隆,它的状态不会更新我该怎么做?
#[derive(Debug, Clone)]
struct Movement {
x: i32,
y: i32,
}
fn main() {
let mut current = Some(Movement { x: 1, y: 2 });
let mut stack = Vec::new();
stack.push(¤t);
current.as_mut().unwrap().x = 2;
println!("m: {:?}", current);
println!("stack.m: {:?}", stack.pop());
current = None;
}
最佳答案
您正试图改变某些东西,同时在其他地方持有对它的共享引用。这是一个问题,因为 Rust 假设共享 ( &
) 引用背后的东西不会被改变,以证明您的代码在多线程上下文中和存在某些优化的情况下是正确的。
要修复它,您可以告诉编译器忘记多线程并跳过这些优化。一种方法是使用 RefCell
:
use std::cell::RefCell;
#[derive(Debug, Clone)]
struct Movement {
x: i32,
y: i32,
}
fn main() {
let mut current = Some(RefCell::new(Movement { x: 1, y: 2 }));
// ^^^^^^^^^^^^ put it in a `RefCell`
let mut stack = Vec::new();
stack.push(¤t);
// note: as_ref, not as_mut
current.as_ref().unwrap().borrow_mut().x = 2;
println!("m: {:?}", current);
println!("stack.m: {:?}", stack.pop());
current = None;
}
如果您需要在不同线程之间共享对象,您可能需要 Mutex
或 RwLock
。如果共享的东西是可以简单复制的东西,比如单个 i32
,您可以使用 Cell<i32>
(非线程安全)或 AtomicI32
(线程安全)。这些统称为内部可变性类型,因为它们允许通过共享引用改变内部值。
但内部可变性只能让你走到这一步。将对局部变量的引用放在 Vec
中不是很灵活,因为 Vec
不能比它引用的任何变量都长寿。一个常见的习惯用法是将对象移动到 Vec
中并使用索引而不是内置引用来访问它们。这是一种方法:
#[derive(Debug, Clone)]
struct Movement {
x: i32,
y: i32,
}
fn main() {
// this object will be moved into the vector
let temp = Some(Movement { x: 1, y: 2 });
let mut stack = Vec::new();
// now we set `current` to be the index of the object in the vector, and use
// `stack[current_index]` to refer to the object itself
let current_index = stack.len();
stack.push(temp);
// you could also do something like this to get a mutable reference, but it
// would prevent you from doing anything else with `stack` until you are done with
// `current` (`stack[current_index]` does not have this limitation):
//let current = stack.last_mut().unwrap()
stack[current_index].as_mut().unwrap().x = 2;
println!("m: {:?}", stack[current_index]);
println!("stack.m: {:?}", stack.pop());
}
还有更多选择。例如,您可以将 RefCell
放入 Rc
(引用计数智能指针)并克隆它以在 Vec
和局部变量之间共享所有权。在没有关于您的目标的更多信息的情况下,我倾向于索引 Vec
以避免共享突变的复杂性,但设计最终是您的选择。
关于rust - 如何在 Vec 中存储引用并稍后在 Rust 中使用它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63404153/
我是一名优秀的程序员,十分优秀!