fn func(s: *mut String, a: *mut i32) -> usize {
println!("{}", unsafe { *s });
println!("{}", unsafe { *a });
unsafe { (*s).len() }
}
fn main() {
let mut s = String::from("hello");
let mut a = 10;
func(&mut s, &mut a);
}
上面的代码失败,错误:
error[E0507]: cannot move out of dereference of raw pointer
--> src/main.rs:2:29
|
2 | println!("{}", unsafe { *s });
| ^^ cannot move out of dereference of raw pointer
为什么String
而不是i32
发生?为什么要抱怨"移动"?
为什么
发生这种情况。String
而不是i32
?
RUST中的基本积分类型(实际上是许多其他类型)实现了Copy
特征。他们具有"复制语义",而不是"移动语义"。这里没有所有权变更...您正在复制该价值。String
不实现 Copy
特征,因此该绑定具有"移动语义"。
这不是原始指针所唯一的,也与它们的可变性有关。此示例表明,这可以通过不变的参考来进行:
fn func(s: &String, a: &i32) {
let _x = *s;
let _x = *a;
}
为什么要抱怨"移动"?
之所以这样做,是因为您正在尝试将所有权从unsafe
块中移出。只要您不关心这一点,就需要在unsafe
块中包含"移动",以便编译器让您的脚射击。因此,如果您重组代码,以便不移动unsafe
块的外部,则代码将编译:
unsafe {
println!("{}", *s);
}
在这里它在操场上运行。
在对您的问题的评论中重新征用Shepmaster的观点...如果"移动"一词对您来说是陌生的,那么您不应首先使用RAW POINTER/unsafe
块,而应该回到Rust的可用文档了解该概念。因为它是核心。