tet*_*one 4 ownership rust borrow-checker
我有一个大型结构体,其中包含 s 向量String作为成员。我试图迭代这些并将每个传递给另一个带有&str参数的方法。后一种方法需要&mut self处理输入流,而我似乎无法协调借用。
我将其归结为一个简单的(?)示例来显示我遇到的问题。请参阅下文,以及Rust 游乐场上代码的链接
pub struct Configuration {
pub prefixes: Vec<String>,
}
impl Configuration {
pub fn check_one(&mut self, prefix: &str) -> bool {
"testy".starts_with(prefix)
}
pub fn check(&mut self) -> bool {
for prefix in &self.prefixes {
if self.check_one(prefix) {
return true;
}
}
return false;
}
}
fn main() {
let mut config = Configuration{ prefixes: vec!["fl".to_string()], };
dbg!(config.check());
}
Run Code Online (Sandbox Code Playgroud)
实际问题。如果我将参数设为引用 ( ),那么我会得到一个由编译器建议移动的self.check_one(&prefix)问题。美好的。但是,如果我尝试这样做,我会被告知,当我已经可变地借用它时,我不能一成不变地借用它,而且我似乎无法调和这两者。self.prefixesinto_iter()&self.prefixesself
最重要的是,我需要将String成员向量中的每个传递给方法进行检查。我不想修改字符串或向量,但我必须借用&self可变的。建议?
无法调用借用&mut self部分时所采用的方法self。这是因为一个方法&mut self允许修改 的任何部分self。您不能创建一个只允许修改self.
如所写,check_one应采取&self. 里面check,&mut self会自动转换为&selfon call check_one。
pub fn check_one(&self, prefix: &str) -> bool {
"testy".starts_with(prefix)
}
Run Code Online (Sandbox Code Playgroud)
如果您需要能够修改 的所有部分self(包括 )prefixes,那么您需要克隆,prefixes以便副本self拥有的内容不被借用。
for prefix in &self.prefixes.clone() {
if self.check_one(prefix) {
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
如果您不需要对 进行可变或不可变访问prefixes,那么您可以执行以下两件事之一。首先,您可以创建一个常规函数来获取self.
// Replace `()` with the other parts of `self`
pub fn check_one(_other_parts: (), prefix: &str) -> bool {
"testy".starts_with(prefix)
}
Run Code Online (Sandbox Code Playgroud)
for prefix in &self.prefixes {
if check_one((), prefix) {
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
或者您可以暂时从 中取出 ,完成后将其放回原处。prefixesself
pub fn check(&mut self) -> bool {
let prefixes = std::mem::take(&mut self.prefixes);
for prefix in &prefixes {
if self.check_one(prefix) {
self.prefixes = prefixes;
return true;
}
}
self.prefixes = prefixes;
return false;
}
Run Code Online (Sandbox Code Playgroud)
最后,一种不太常见的情况是check_one可能会或可能不会prefixes根据数据进行修改。在这种情况下,为了仅prefixes在必要时进行克隆,您可以使用Rc或Arc。这是一个更广泛的变化。
pub struct Configuration {
pub prefixes: Rc<Vec<String>>,
}
impl Configuration {
pub fn check_one(&mut self, prefix: &str) -> bool {
let check = "testy".starts_with(prefix);
// Do some mutable work
if check {
Rc::make_mut(&mut self.prefixes).push("new".to_string());
}
return check;
}
pub fn check(&mut self) -> bool {
// The only change needed here is a dereference
for prefix in &*self.prefixes.clone() {
if self.check_one(prefix) {
return true;
}
}
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
当您克隆Rc自身时,它会创建第二个指向相同数据的只读引用。make_mut当存在多个引用时,调用将克隆数据,从而为您提供对数据的可变访问。在这种情况下,第一次make_mut调用时,数据将被克隆,Rc将用包含克隆数据的新数据替换自身Rc,并返回可变引用。如果make_mut在同一个循环中再次调用,它将简单地返回一个可变引用,因为它不再链接到另一个Rc.
| 归档时间: |
|
| 查看次数: |
80 次 |
| 最近记录: |