Pointers 取消对字符串的原始指针和对i32的原始指针的引用之间有什么区别?

Pointers 取消对字符串的原始指针和对i32的原始指针的引用之间有什么区别?,pointers,rust,borrow-checker,ownership-semantics,Pointers,Rust,Borrow Checker,Ownership Semantics,上述代码失败,出现错误: 错误[E0507]:无法移出原始指针的取消引用 ->src/main.rs:2:29 | 2 | println!{},不安全的{*s}; |^^无法移出原始指针的取消引用 为什么它发生在String而不是i32上?它为什么抱怨搬家 为什么它发生在String而不是i32上 基本的积分类型,事实上,许多其他类型的铁锈工具。它们具有复制语义,而不是移动语义。这里的所有权没有变化。。。您正在复制该值。字符串不实现复制特性,因此此绑定具有移动语义 这不是原始指针所独有的,也与

上述代码失败,出现错误:

错误[E0507]:无法移出原始指针的取消引用 ->src/main.rs:2:29 | 2 | println!{},不安全的{*s}; |^^无法移出原始指针的取消引用 为什么它发生在String而不是i32上?它为什么抱怨搬家

为什么它发生在String而不是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);
}
它为什么抱怨搬家

它这样做是因为您试图将所有权移出不安全的块。只要你不在乎这一点,那么你就需要将移动包含在不安全的块中,这样编译器就可以让你射中自己的脚。因此,如果您重新构造代码,使其不会移出不安全块,则代码将编译:

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

在对你的问题的评论中再次重申谢普马斯特的观点。。。如果术语“移动”听起来很陌生,那么您首先不应该使用原始指针/不安全的块,而是应该回到可用的文档中了解该概念。。因为它是一个核心

为什么它发生在String而不是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);
}
它为什么抱怨搬家

它这样做是因为您试图将所有权移出不安全的块。只要你不在乎这一点,那么你就需要将移动包含在不安全的块中,这样编译器就可以让你射中自己的脚。因此,如果您重新构造代码,使其不会移出不安全块,则代码将编译:

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


在对你的问题的评论中再次重申谢普马斯特的观点。。。如果术语“移动”听起来很陌生,那么您首先不应该使用原始指针/不安全的块,而是应该回到可用的文档中了解该概念。。因为它是一个核心指针。

为什么它会抱怨移动-如果你不知道移动在Rust中的含义,你可能还不应该使用原始指针。返回并重新阅读整个介绍性书籍,您可以使用std::ptr::read复制原始字符串数据,但这很容易导致未定义的行为。为什么它会抱怨移动?如果您不知道移动在Rust中的含义,您可能还不应该使用原始指针。返回并重新阅读整个介绍性书籍,您可以使用std::ptr::read复制原始字符串数据,但这很容易导致未定义的行为。因此,在调用println!时会发生所有权转移?我的意思是为什么它适用于'let x=String::from hello;普林顿!{},x;普林顿!{},x;`。我有点困惑为什么第二次打印!那么成功了吗?另外,请您详细说明一下,这是因为您试图将所有权移出不安全区块。请容忍我的沉默questions@soupybionics普林顿!不获取所有权,但必须将值从块内部移动到块外部。{}块通过将值*s变成临时值来强制移动,就像不安全块那样。普林顿!{},*s;会有用的。但普林顿也是!{},s.@trentcl,谢谢!我还是不明白。不安全的{*s;}和不安全的{println!{},*s;}@soupyboonics之间有什么区别?区别在于println!auto引用它的参数,所以在*s前面有一个隐式的。我链接的第一个问答就解释了这一点。非常感谢Trentl!我想我现在明白要点了。基本上,代码让a=String::fromabc;A.println{},a;触发所有权的移动转移,导致println错误!正如所料。因此,在不安全{*s;}的情况下,再次出现了临时所有权转移的趋势,就像上面的abc示例一样。没别的了。我希望我的理解是正确的:那么在调用println!时会发生所有权转移?我的意思是为什么它适用于'let x=String::from hello;普林顿!{},x;普林顿!{},x;`。我有点困惑为什么第二次打印!那么成功了吗?另外,你能详细说明一下吗
因为您试图将所有权移出不安全区块。请容忍我的沉默questions@soupybionics普林顿!不获取所有权,但必须将值从块内部移动到块外部。{}块通过将值*s变成临时值来强制移动,就像不安全块那样。普林顿!{},*s;会有用的。但普林顿也是!{},s.@trentcl,谢谢!我还是不明白。不安全的{*s;}和不安全的{println!{},*s;}@soupyboonics之间有什么区别?区别在于println!auto引用它的参数,所以在*s前面有一个隐式的。我链接的第一个问答就解释了这一点。非常感谢Trentl!我想我现在明白要点了。基本上,代码让a=String::fromabc;A.println{},a;触发所有权的移动转移,导致println错误!正如所料。因此,在不安全{*s;}的情况下,再次出现了临时所有权转移的趋势,就像上面的abc示例一样。没别的了。我希望我理解正确: