将原始指针与字符串指针与i32的原始指针指定之间有什么区别


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的可用文档了解该概念。因为它是核心。

相关内容

  • 没有找到相关文章

最新更新