我有这样的功能:
extern {
fn foo(layout: *const RawLayout) -> libc::uint8_t;
}
fn bar(layout: Layout) -> bool {
unsafe {
foo(&layout.into() as *const _) != 0
}
}
其中Layout
是可以转换的可复制类型.into()
和RawLayout
。
我想确保我了解正在发生的事情,因为它不安全。据我了解,layout.into()
创建了一个临时RawLayout
,然后&
对其进行了引用,as *const _
将其转换为原始指针(*const RawLayout
) 。然后调用foo()
函数并返回,最后删除临时RawLayout
。
这是对的吗?或者,为什么我不应该这样做有一些棘手的原因?
答案 0 :(得分:4)
你是对的。在这种情况下,首先调用foo
,然后删除RawLayout
。这在The Rust Reference中有解释(请点击链接查看实践中如何解决的具体示例):
临时值的生命周期通常是最里面的封闭 声明
但是,我更愿意遵循Shepmaster的建议。明确地引入局部变量将有助于代码的读者集中于更重要的事情,例如确保不安全的代码是正确的(而不是必须弄清楚临时变量的确切语义)。
您可以使用以下代码检查此行为:
struct Layout;
struct RawLayout;
impl Into<RawLayout> for Layout {
fn into(self) -> RawLayout {
RawLayout
}
}
impl Drop for RawLayout {
fn drop(&mut self) {
println!("Dropping RawLayout");
}
}
unsafe fn foo(layout: *const RawLayout) -> u8 {
println!("foo called");
1
}
fn bar(layout: Layout) -> bool {
unsafe {
foo(&layout.into() as *const _) != 0
}
}
fn main() {
bar(Layout);
}
输出结果为:
foo called
Dropping RawLayout