sou*_*ics 1 pointers ownership-semantics rust borrow-checker
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);
}
Run Code Online (Sandbox Code Playgroud)
上面的代码失败并出现错误:
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);
}
Run Code Online (Sandbox Code Playgroud)
为什么它发生为String而不是为i32?为什么它抱怨“移动”?
为什么它发生为
String而不是为i32?
Rust 中的基本整数类型(实际上还有许多其他类型)实现了Copytrait。它们具有“复制语义”,而不是“移动语义”。这里没有所有权变更……您正在复制价值。String 没有实现的Copy特点,因此这种结合具有“移动语义”。
这不是原始指针独有的,也与它们的可变性没有任何关系。这个例子表明这可能发生在不可变引用中:
fn func(s: &String, a: &i32) {
let _x = *s;
let _x = *a;
}
Run Code Online (Sandbox Code Playgroud)
为什么它抱怨“移动”?
这样做是因为您试图将所有权移出该unsafe块。只要你不关心这个,那么你就需要在unsafe块中包含“移动”,这样编译器就会让你用脚射击自己。因此,如果您重构代码以便不移动到unsafe块之外,代码将编译:
unsafe {
println!("{}", *s);
}
Run Code Online (Sandbox Code Playgroud)
不过,要重申 Shepmaster 在对您的问题的评论中的观点……如果“移动”一词对您来说听起来很陌生,那么您首先不应使用原始指针/unsafe块,而应返回可用的文档Rust 来理解这个概念......因为它是一个核心概念。