英文:
cannot move out of `keymap.command` which is behind a shared reference
问题
以下是用于运行终端命令的模拟代码:
#[derive(Debug)]
pub struct Keymap {
    pub key: char,
    pub command: String,
}
impl Keymap {
    pub fn new<S: AsRef<str>>(key: char, command: S) -> Self {
        let command = command.as_ref().to_owned();
        Self {
            key,
            command,
        }
    }
}
fn handle_keymap(keymap: &Keymap) {
    println!("使用键映射执行某些操作:{:?}", keymap);
    run_command(&keymap.command);
}
fn run_command(command_string: &str) {
    let command_string = command_string.replace("test", "best");
    println!("运行此命令:{:?}", command_string);
}
fn main() {
    let keymap = vec![Keymap::new('t', "echo 'test'")].into_iter().next().unwrap();
    handle_keymap(&keymap);
}
现在,这个代码不再使用 clone(),而是通过将 run_command 函数修改为接受 &str 参数来避免移动 keymap.command。这是一种更好的做法,因为它避免了不必要的内存分配和拷贝。
英文:
The following is a mock code for running a terminal command:
#[derive(Debug)]
pub struct Keymap {
    pub key: char,
    pub command: String,
}
impl Keymap {
    pub fn new<S: AsRef<str>>(key: char, command: S) -> Self {
        let command = command.as_ref().to_owned();
        Self {
            key,
            command,
        }
    }
}
fn handle_keymap(keymap: &Keymap) {
    println!("Do something with the keymap: {:?}", keymap);
    run_command(keymap.command);
}
fn run_command(command_string: String) {
    let command_string = command_string.replace("test", "best");
    println!("Running this command: {:?}", command_string);
}
fn main() {
    let keymap = vec![Keymap::new('t', "echo 'test'")].into_iter().next().unwrap();
    handle_keymap(&keymap);
}
Right now, there's an error here:
error[E0507]: cannot move out of `keymap.command` which is behind a shared reference
  --> src/main.rs:21:17
   |
21 |     run_command(keymap.command);
   |                 ^^^^^^^^^^^^^^ move occurs because `keymap.command` has type `String`, which does not implement the `Copy` trait
Which can be solved by using clone():
run_command(keymap.command.clone());
Is there another solution? I think using clone() like this isn't good practice?
答案1
得分: 1
函数run_command 拥有 传递的 String 参数的所有权。但它无法这样做,因为 keymap.command 在一个共享引用后面。根据您想要做什么,您应该执行以下其中之一:
- 
如果您想要
run_command更改传递的命令,但不要为调用者反映这一更改,您应该保留run_command如现在所示,并确实在keymap.command上调用clone()。您可以将&String(或&str)传递给run_command并在内部克隆它,但最好将该决策留给调用者。 - 
如果您想要
run_command更改实际的keymap.command,请传递一个&mut String。这还将强迫您更改handle_keymap,以接受&mut Keymap而不是&Keymap。 - 
如果您不想在
run_command内部更改命令,那么不要这样做,并将其更改为通过引用获取字符串&String(或者更好地利用 deref coercion 并将command传递为&str)。 
如果您想要不同的东西,您将需要在您的问题中更具体,以便我们帮助您。
英文:
Function run_command takes an ownership of passed String argument. But it cannot do that, since keymap.command is behind a shared reference. Depending on what you are trying to do you should do one of the following:
- 
If you want
run_commandto change passed command, but not reflect that for the caller you should leaverun_commandas it is now and indeed callclone()onkeymap.command. You could pass&String(or&str) torun_commandand clone it inside, but it is better to leave that decision to the caller. - 
If you want
run_commandto change actualkeymap.commandpass it a&mut Stringinstead. This will also force you to changehandle_keymapto take&mut Keymapinstead of&Keymap. - 
If you don't want to mutate command inside
run_commandthen don't do it and change it to take string by reference&String(or event better take advantage of deref coercion and passcommandas&str). 
If you want something different, you will have to be more specific in your question for us to help you.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论