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

问题描述 投票:0回答:1
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?为什么抱怨“举动”?

pointers rust borrow-checker ownership-semantics
1个回答
4
投票

为什么String而不是i32

Rust中的基本整数类型(实际上是许多其他类型)实现了the Copy trait。他们有“复制语义”,而不是“移动语义”。这里所有权没有变化......你正在复制价值。 String没有实现Copy特性,因此这种绑定具有“移动语义”。

这不是原始指针所特有的,也不与它们的可变性有任何关系。 This example shows这可能发​​生在不可变引用:

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

为什么抱怨“举动”?

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

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

Here it is running in the playground

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

© www.soinside.com 2019 - 2024. All rights reserved.