取消引用指向String的原始指针和指向i32的原始指针有什么区别?

时间:2017-12-19 04:02:42

标签: pointers rust borrow-checker ownership-semantics

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?为什么抱怨“移动”?

1 个答案:

答案 0 :(得分:4)

  

为什么String而不是i32呢?

Rust实现how to convert a bit mask prefix into a dotted-decimal notation中的基本整数类型(实际上是许多其他类型)。他们有“复制语义”,而不是“移动语义”。这里所有权没有变化......你正在复制价值。 String 未实现 Copy特征,因此此绑定具有“移动语义”。

这不是原始指针所特有的,也不与它们的可变性有任何关系。 the Copy trait使用不可变引用会发生这种情况:

fn func(s: &String, a: &i32) {
    let _x = *s;
    let _x = *a;
}
  

为什么抱怨“移动”?

这样做是因为您试图将所有权移出unsafe块。只要您对此无关紧要,那么您需要在unsafe块中包含“移动”,这样编译器就可以让您自己动手。因此,如果您重构代码以便不移动到unsafe块的之外,代码将编译:

unsafe {
    println!("{}", *s);
}

This example shows

要重新讨论Shepmaster在你的问题评论中的观点...如果术语“移动”听起来很陌生,那么你不应该首先使用原始指针/ unsafe块,并且应该而是回到Rust的可用文档来理解这个概念......因为它是核心概念。