为什么在这里移动字符串变量会出错?

3
use std::collections::HashMap;
#[derive(Clone,Debug)]
pub enum Address {
    Ptr(Box<Node>),
    None,
}

#[derive(Clone,Debug)]
pub struct Node {
    connection: String,
    value: i32,
    next: Address,
}

impl Node {

    pub fn new(connection:String, value: i32) -> Node{
        Node{
            connection,
            value,
            next: Address::None,
        }
    }

    pub fn insert(&mut self, connection: String, value: i32) {
        match self.next {
            Address::Ptr(ref mut v) => {
                v.insert(connection,value);
            }
            Address::None => {
                self.next = Address::Ptr(Box::new(Node{connection,value,next:Address::None}))
            }
        }
    }
    
}


struct GraphAdj {
    vec_edge: HashMap<String,Node>
}

impl GraphAdj {
    pub fn new() -> GraphAdj{
        GraphAdj{
            vec_edge: HashMap::new(),
        }
    }

    pub fn insert(&mut self, value: String) -> Result<(),String> {

        if self.vec_edge.contains_key(&value) {
            return Err(format!("Key already present"))
        }

        self.vec_edge.insert(value,
            Node::new(String::from(""),-1)
        );
        Ok(())
    } 

    pub fn add_connection(&mut self, 
        source_vertex: String,
        destination_vertex: String,
        cost: i32,
    ){

        for (key,value) in self.vec_edge.iter_mut() {
            if *key == source_vertex {
                value.insert(destination_vertex,cost);
            } 
        }
    }

}
fn main(){}

我遇到了以下错误。
***cargo check
    Checking rust_graph v0.1.0 (D:\projects\DSA\graph\rust_graph)
error[E0382]: use of moved value: `destination_vertex`
  --> src\main.rs:36:30
   |
30 |         destination_vertex: String,
   |         ------------------ move occurs because `destination_vertex` has type `String`, which does not implement the `Copy` trait
...
36 |                 value.insert(destination_vertex,cost);
   |                              ^^^^^^^^^^^^^^^^^^ value moved here, in previous iteration of loop
error: aborting due to previous error***

***For more information about this error, try `rustc --explain E0382`.
error: could not compile `rust_graph`
To learn more, run the command again with --verbose.***

我知道String变量被移动了,但为什么这是个问题呢?我的意思是我之后也不会再使用它了。


5
你分享的代码似乎与错误无关。你错误信息中的“destination_vertex”名称在代码中并未出现。请提供一个 MVCE - GManNickG
你之后使用它:你在循环中使用它。该值在循环第一次运行时移动,因此在循环第二次运行时不可用。 - Jmb
你可能只需要clone()目标顶点:value.insert(destination_vertex.clone(), cost)。由于Node::insert接受一个拥有所有权的String,所以你必须提供一个克隆版本,否则无法绕过这个问题。 - user4815162342
如果向量中的key是唯一的,则在插入值后可以使用breakreturn。否则,就像@user4815162342所说,您需要克隆destination_vertex,以便在未来的迭代中保留副本。 - Jmb
insert() 可以使用引用,但仍然必须创建一个真正的 String 来创建一个 Node。因此,它要么必须创建一个拥有的字符串(相当于要求调用者进行 clone()),要么您需要更改 Node 以存储引用,这将需要将生命周期信息附加到 Node 并确保 Node 不会超出字符串的生命周期。换句话说,在那里几乎肯定 想使用引用。 - user4815162342
显示剩余6条评论
1个回答

3

以下是出错的函数:

   pub fn add_connection(
        &mut self,
        source_vertex: String,
        destination_vertex: String,
        cost: i32,
    )
    {
        for (key, value) in self.vec_edge.iter_mut() {
            if *key == source_vertex {
                value.insert(destination_vertex, cost);
            }
        }
    }

以下是我们发生错误的insert()函数的定义:

pub fn insert(&mut self, connection: String, value: i32)

你有一个 String 实例,你试图多次移动它,通过将其作为参数传递给 insert()。每次循环调用都会移动字符串,一旦移动了一次,就无法再移动。

编译器无法知道此循环会有多少次迭代,或者条件 *key == source_vertex 会评估为 true 的次数,因此它假定可能会发生多次。

为了解决错误,您需要 clone() 字符串并移动(作为参数传递)克隆:

  for (key, value) in self.vec_edge.iter_mut() {
       if *key == source_vertex {
           value.insert(destination_vertex.clone(), cost);
       }
  }

或者在值已被移动后从循环中跳出:

for (key, value) in self.vec_edge.iter_mut() {
    if *key == source_vertex {
       value.insert(destination_vertex, cost);
       return; // or break; -> exit from the loop or method
    }
}

谢谢。我不知道递归会让编译器感到困惑,但这很有道理。 - Nishan Maharjan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接