作为 Rust 的初学者,我突然对 Rust 中的
move
语义以及所有权转移时数据是否被复制感到好奇。
#[derive(Debug)]
struct Foo {
name: i32,
age: i32,
}
fn main() {
let foo = Foo { name: 111, age: 1 };
let ptr_foo = std::ptr::addr_of!(foo);
println!("Address of foo: {:p}", ptr_foo);
let bar = foo;
let ptr_bar = std::ptr::addr_of!(bar);
println!("Address of bar: {:p}", ptr_bar);
}
我最初以为“有一个变量 foo,移动后,我们简单地将其重命名为 bar”,从而避免了复制其对应数据的需要。
为了进一步调查,我使用了 VSCode 中的调试功能以及名为“Hex Editor”的插件,发现
foo
和 bar
(内存地址 0x7fffffffd7d8
和 0x7fffffffd828
)包含相同的数据 (6F 00 00 00 01 00 00 00
) ).
这是否表明 Rust 即使在
move
期间实际上也会执行复制操作,例如在本例中复制结构?此行为是否会根据是否处于发布模式而有所不同?
“移动”在许多语言(不仅仅是 Rust)中是一个语义术语,指的是“所有权转移”,并且并不“必然”规定该转移的机制。 在 Rust 中,移动值会将数据复制到其他位置,但会使值的源不可用(除非该源稍后使用有效值重新初始化)。
这是如何实现的,Rust 是从源到目标的按位复制。 在更高的优化级别上,可以忽略此副本,但也可能不会。 特别是,获取 foo
bar
的地址可能会阻止优化器实际删除副本,因为它无法统一它们的内存位置。
换句话说:
如果您试图查看代码将如何编译,
不要更改该代码以检查代码内部的值,否则您几乎肯定会以某种方式更改优化器的行为。 相反,请查看生成的机器代码。