这里记录了Rust的移动语义的一个很好的例子:在Rust By Example网站上的Rust Move Semantics .
我对两个案例都有基本的了解 . 第一个原语是如何使用原语可以使用新的别名,原始文件仍可以使用,因为最终结果是 i32
使用 Copy
特征时看到的副本 . 这对我来说很有意义 .
此外,由于许多充分的理由,第二个示例在具有多个引用堆上的 i32
的别名方面是有意义的 . Rust强制执行所有权规则,因此现在无法使用原始别名创建新绑定 . 这有助于防止数据争用,双重释放等 .
但似乎还有第三个案例没有被谈到 . How does Rust implement moves of stack allocated structs that do not implement the Copy trait? 使用以下代码说明:
#[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 will allocate the Employee on the stack . 上面的结构 does not implement the Copy trait 因此在分配给新别名时不会被复制 . 这对我来说非常混乱,因为如果在堆栈上分配了 Employee
结构,并且没有实现 Copy
特性在哪里/如何移动?它是否物理移动到 do_something()
的堆栈帧?
在解释这个难题时,我们对任何帮助表示赞赏 .
1 回答
是 . 非
Copy
类型的物理移动与Copy
类型完全相同:带有memcpy
. 您已经了解原始Copy
-types会逐字节地复制到新位置(例如新的堆栈帧) .现在考虑
Box
的这个实现:当你有
然后在堆上分配
i32
,Box
将原始指针保存到该堆分配的内存 . 请注意,Box
直接(内部的原始指针)直接在堆栈上,而不是在堆上!只是i32
在堆上 .当_1274152被移动时,正如我刚才所说的那样 . 这意味着堆栈内容被复制(!!)...因此只需逐个字节地复制指针 . 没有
i32
的第二个版本!在物理移动方面,
Copy
和非Copy
类型之间没有区别 . 唯一的区别是编译器对这些类型强制执行不同的规则 .