gpt4 book ai didi

rust - Rust 如何 move 不可复制的堆栈变量?

转载 作者:行者123 更新时间:2023-11-29 07:42:17 31 4
gpt4 key购买 nike

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

我对所展示的两种情况都有基本的了解。第一个是基元如何可以有一个新的别名,并且原始的仍然可以使用,因为最终结果是一个副本,因为 i32 使用了 Copy 特性。这对我来说很有意义。

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

不过好像还有第三种情况没有讲到。 Rust 如何实现未实现 Copy 特性的堆栈分配结构的 move ?以下代码对此进行了说明:

#[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 trait,因此在分配给新别名时不会被复制。这让我很困惑,因为如果 Employee 结构被分配在堆栈上并且也没有实现 Copy 特征,它会在哪里/如何 move ?它是否实际 move 到 do_something() 的栈帧?

感谢任何帮助解释这个难题。

最佳答案

Does it physically get moved to do_something()'s stack frame?

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

现在考虑 Box 的实现:

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

当你有

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

然后 i32 被分配到堆上,Box 将原始指针保存到堆分配的内存中。注意,Box直接(里面的裸指针)是直接在栈上的,不是在堆上!只有 i32 在堆上。

Box 被 move 时,它被 memcpy 编辑,正如我刚才所说的。这意味着堆栈内容被复制(!!)...因此只是指针被逐字节复制。 i32 没有第二个版本!

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

关于rust - Rust 如何 move 不可复制的堆栈变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36230710/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com