一个可变引用的问题

从rust社区看到的一个问题,原文地址:https://users.rust-lang.org/t/calling-a-mu...

问题描述

题主实现如下代码,报错:

use std::collections::HashMap;

struct MyData {
    d: f32
}

struct Foo {
    d: HashMap<String, MyData>
}

impl Foo {
    fn get(&mut self, s: &str) -> Option<&MyData> {
        if !self.d.contains_key(s) {
            self.d.insert(s.to_string(), MyData{ d: 0.0 });
        }
        self.d.get(s)
    }
}

fn main() {
    let mut foo = Foo {
        d: HashMap::new() 
    };

    let mut saved = Vec::new();

    for _i in 1..3 {
        let l = foo.get("a");
        saved.push(l);
    }
}

问题解决

方法一

use std::collections::HashMap;

#[derive(Clone, Copy)]
struct MyData {
    d: f32
}

struct Foo {
    d: HashMap<String, MyData>
}

impl Foo {
    fn get(&mut self, s: &str) -> Option<MyData> {
        if !self.d.contains_key(s) {
            self.d.insert(s.to_string(), MyData{ d: 0.0 });
        }
        self.d.get(s).copied()
    }
}

fn main() {
    let mut foo = Foo {
        d: HashMap::new() 
    };

    let mut saved = Vec::new();

    for _i in 1..3 {
        let l = foo.get("a");
        saved.push(l);
    }
}

方法二

use std::collections::HashMap;

struct Foo {
    d: HashMap<String, f32>
}

impl Foo {
    fn get(&mut self, s: &str) -> Option<f32> {
        if !self.d.contains_key(s) {
            self.d.insert(s.to_string(), 0.0);
        }
        self.d.get(s).copied()
    }
}

fn main() {
    let mut foo = Foo {
        d: HashMap::new() 
    };

    let mut saved = Vec::new();

    for _i in 1..3 {
        let l = foo.get("a");
        saved.push(l);
    }
}
令狐一冲
讨论数量: 1

第一眼看到了下感觉没啥问题,执行了下确实报错了

mutable borrow starts here in previous iteration of loop
// 也就是这一行
 let l = foo.get("a");

自己理解的

主要是编译器的借用安全检查阻止,因为get方法返回的是对map中元素的一个引用,并且绑定到了Vec,编译器认为第二次对Foo的可变引用会造成内存的不安全,所以阻止

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!