Rust 为什么结构的地址与被删除的地址不同?
Rust why is the address of struct not the same address that is being dropped?
我有这个代码:
struct Example {
x: i32,
b: Option<Box<Example>>,
}
impl Example {
fn get_self(&self) -> String {
format!("{:p}", self)
}
}
impl Drop for Example {
fn drop(&mut self) {
println!("Droppped: {} {:p}", self.x, self);
}
}
fn take(t: Example) {
println!("Taken ownership");
}
fn main() {
let mut myE = Example {
x: 1,
b: Some(Box::new(Example { x: 2, b: None })),
};
println!(
"Parent: {} Child: {}",
myE.get_self(),
match &myE.b {
Some(x) => x.get_self(),
None => String::from("Error"),
}
);
take(myE);
println!("End!");
}
这是输出
Parent: 0x7ffdc8031560 Child: 0x556b88bb5ba0
Taken ownership
Droppped: 1 0x7ffdc80314a8
Droppped: 2 0x556b88bb5ba0
End!
请注意子地址与一旦超出范围就被删除的地址相同,但一旦父超出范围,它就会因某种原因发生变化。这是什么原因?
我希望输出是这样的:
Parent: 0x7ffdc8031560 Child: 0x556b88bb5ba0
Taken ownership
Droppped: 1 0x7ffdc8031560
Droppped: 2 0x556b88bb5ba0
End!
其中打印的地址与删除的地址相同。
这是在行动。当您按值传递某些内容时,它可以在内存中逐字移动。通常,出于效率原因,编译器可能会选择不移动某些内容,但您应该始终假设任何移动值的操作 可以 物理移动它。
确切的行为可能会随着不同的 Rust 版本、调试与发布版本、内联提示、link-time 优化、目标操作系统或体系结构而改变,或者只是你添加了另一行代码改变了栈帧的最佳布局。在所有情况下,您可以做出的唯一假设是移动的值 可能 最终位于内存中的不同位置。
举一个更简单的例子,你甚至不需要将值移动到另一个函数中:
fn main() {
let mut myE = Example {
x: 1,
b: Some(Box::new(Example { x: 2, b: None })),
};
println!("Parent: {} Child: {}", myE.get_self(), match &myE.b {
Some(x) => x.get_self(),
None => String::from("Error")
});
// move the value
let moved = myE;
println!("End!");
}
这仍然会移动内存中的数据(至少在我 运行 它时,在调试版本中)。
装箱值不同,因为它是在堆上分配的。 Box
实际上只是一个指针,只是移动了指针;它指向的数据保留在同一个地方。
我有这个代码:
struct Example {
x: i32,
b: Option<Box<Example>>,
}
impl Example {
fn get_self(&self) -> String {
format!("{:p}", self)
}
}
impl Drop for Example {
fn drop(&mut self) {
println!("Droppped: {} {:p}", self.x, self);
}
}
fn take(t: Example) {
println!("Taken ownership");
}
fn main() {
let mut myE = Example {
x: 1,
b: Some(Box::new(Example { x: 2, b: None })),
};
println!(
"Parent: {} Child: {}",
myE.get_self(),
match &myE.b {
Some(x) => x.get_self(),
None => String::from("Error"),
}
);
take(myE);
println!("End!");
}
这是输出
Parent: 0x7ffdc8031560 Child: 0x556b88bb5ba0
Taken ownership
Droppped: 1 0x7ffdc80314a8
Droppped: 2 0x556b88bb5ba0
End!
请注意子地址与一旦超出范围就被删除的地址相同,但一旦父超出范围,它就会因某种原因发生变化。这是什么原因?
我希望输出是这样的:
Parent: 0x7ffdc8031560 Child: 0x556b88bb5ba0
Taken ownership
Droppped: 1 0x7ffdc8031560
Droppped: 2 0x556b88bb5ba0
End!
其中打印的地址与删除的地址相同。
这是
确切的行为可能会随着不同的 Rust 版本、调试与发布版本、内联提示、link-time 优化、目标操作系统或体系结构而改变,或者只是你添加了另一行代码改变了栈帧的最佳布局。在所有情况下,您可以做出的唯一假设是移动的值 可能 最终位于内存中的不同位置。
举一个更简单的例子,你甚至不需要将值移动到另一个函数中:
fn main() {
let mut myE = Example {
x: 1,
b: Some(Box::new(Example { x: 2, b: None })),
};
println!("Parent: {} Child: {}", myE.get_self(), match &myE.b {
Some(x) => x.get_self(),
None => String::from("Error")
});
// move the value
let moved = myE;
println!("End!");
}
这仍然会移动内存中的数据(至少在我 运行 它时,在调试版本中)。
装箱值不同,因为它是在堆上分配的。 Box
实际上只是一个指针,只是移动了指针;它指向的数据保留在同一个地方。