在不复制的情况下取得 String 的所有权
Taking ownership of a &String without copying
上下文
这是我运行
的人为复制
fn main() {
let mut s = String::from("Hello World");
example(&mut s);
}
fn example(s: &mut str) -> Option<String> {
other_func(Some(s.to_owned()))
// other random mutable stuff happens
}
fn other_func(s: Option<String>) {
match s {
Some(ref s) => other_func2(*s),
None => panic!()
}
}
fn other_func2(s: String) {
println!("{}", &s)
}
和错误
Compiling playground v0.0.1 (/playground)
error[E0507]: cannot move out of `*s` which is behind a shared reference
--> src/main.rs:12:36
|
12 | Some(ref s) => other_func2(*s),
| ^^ move occurs because `*s` has type `String`, which does not implement the `Copy` trait
问题
在下面的代码中,为什么我不能在不执行某种 clone/copy 的情况下引用 &String
?即这不起作用
fn other_func(s: Option<String>) {
match s {
Some(ref s) => other_func2(*s),
None => panic!()
}
}
但如果我将 *s
替换为 s.to_owned()/s.to_string()/s.clone()
它会起作用
顺便说一句,我知道这可能可以通过重构使用 &str
来解决,但我特别感兴趣的是转向 &String -> String
为什么编译器允许你这样做?
s
是 &String
。如果不进行克隆,就无法从 &String
中获取 String
。这很明显。
它是从拥有的 String
创建的?编译器不在乎,它是对的。这与以下代码没有区别:
let s: String = ...;
let r: &String = ...;
let s2: String = *r; // Error
这与以下代码没有什么不同,例如,就编译器而言:
let r: &String = ...;
let s: String = *s;
而且我们的开头不再有自有字符串。通常,编译器不跟踪数据流。确实如此 - 当它 type-checks 移动时,它甚至无法确认此引用没有别名。或者不再使用拥有的值。引用只是引用,它们没有给您删除值的权利。
更改在一般情况下是不可行的(例如,编译器必须跟踪跨函数调用的数据流),并且需要某种形式的手动注释来说明“此值是我的”。你已经有了这样的注释——使用一个拥有的值,String
,而不是 &String
:这正是它的意义所在。
上下文
这是我运行
的人为复制fn main() {
let mut s = String::from("Hello World");
example(&mut s);
}
fn example(s: &mut str) -> Option<String> {
other_func(Some(s.to_owned()))
// other random mutable stuff happens
}
fn other_func(s: Option<String>) {
match s {
Some(ref s) => other_func2(*s),
None => panic!()
}
}
fn other_func2(s: String) {
println!("{}", &s)
}
和错误
Compiling playground v0.0.1 (/playground)
error[E0507]: cannot move out of `*s` which is behind a shared reference
--> src/main.rs:12:36
|
12 | Some(ref s) => other_func2(*s),
| ^^ move occurs because `*s` has type `String`, which does not implement the `Copy` trait
问题
在下面的代码中,为什么我不能在不执行某种 clone/copy 的情况下引用 &String
?即这不起作用
fn other_func(s: Option<String>) {
match s {
Some(ref s) => other_func2(*s),
None => panic!()
}
}
但如果我将 *s
替换为 s.to_owned()/s.to_string()/s.clone()
顺便说一句,我知道这可能可以通过重构使用 &str
来解决,但我特别感兴趣的是转向 &String -> String
为什么编译器允许你这样做?
s
是 &String
。如果不进行克隆,就无法从 &String
中获取 String
。这很明显。
它是从拥有的 String
创建的?编译器不在乎,它是对的。这与以下代码没有区别:
let s: String = ...;
let r: &String = ...;
let s2: String = *r; // Error
这与以下代码没有什么不同,例如,就编译器而言:
let r: &String = ...;
let s: String = *s;
而且我们的开头不再有自有字符串。通常,编译器不跟踪数据流。确实如此 - 当它 type-checks 移动时,它甚至无法确认此引用没有别名。或者不再使用拥有的值。引用只是引用,它们没有给您删除值的权利。
更改在一般情况下是不可行的(例如,编译器必须跟踪跨函数调用的数据流),并且需要某种形式的手动注释来说明“此值是我的”。你已经有了这样的注释——使用一个拥有的值,String
,而不是 &String
:这正是它的意义所在。