繁体   English   中英

Rust如何移动不可复制的堆栈变量?

[英]How does Rust move stack variables that are not Copyable?

这里记录了Rust的移动语义的一个很好的例子:在Rust By Example网站上的Rust Move Semantics

我对两个案例都有基本的了解。 第一个是原语如何拥有一个新的别名,原始的仍然可以使用,因为最终结果是一个副本,因为i32使用了Copy特征。 这对我来说很有意义。

此外,由于许多充分的理由,第二个示例在具有多个引用堆上的i32别名方面是i32的。 Rust强制执行所有权规则,因此现在无法使用原始别名创建新绑定。 这有助于防止数据争用,双重释放等。

但似乎还有第三个案例没有被谈到。 Rust如何实现堆栈分配结构的移动,这些结构没有实现Copy特征? 使用以下代码对此进行说明:

#[derive(Debug)]
struct Employee{
    age: i32,
}

fn do_something(m: Employee){
    println!("{:?}", m);
}

fn main() {
    let x = Employee {
        age: 25,
    };

    do_something(x);

    //compiler error below because x has moved
    do_something(x);
}

我知道:在上面的例子中, Rust将在堆栈上分配Employee 上述结构不实现Copy特征 ,因此在分配给新别名时不会被复制。 这对我来说非常困惑,因为如果在堆栈上分配Employee结构并且还没有实现Copy trait where / how如何移动? 它是否实际上被移动到do_something()的堆栈帧?

在解释这个难题时,任何帮助都会受到赞赏。

它是否实际上被移动到do_something()的堆栈帧?

是。 Copy类型的物理移动方式与Copy类型完全相同:使用memcpy 您已经了解原始Copy -types Copy逐字节地复制到新位置(例如,新的堆栈帧)。

现在考虑Box这个实现:

struct Box<T> {
    ptr: *const T,
}

当你有

let b = Box::new(27i32);
do_something(b);    // `b` is moved into `do_something`

然后在i32分配i32Box将原始指针保存到堆分配的内存中。 请注意, Box直接(内部的原始指针)直接在堆栈上,而不是在堆上! 只是i32在堆上。

Box被移动时,就像我刚刚说的那样,它被memcpy 这意味着堆栈内容被复制(!!)...因此只需逐个字节地复制指针。 没有i32的第二个版本!

在物理移动方面, Copy和非Copy类型之间没有区别。 唯一的区别是编译器对这些类型强制执行不同的规则。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM