我有这样一个函数:

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.

对吗?还是有什么棘手的原因让我不该这么做?

推荐答案

你是对的.在这种情况下,首先调用foo,然后丢弃RawLayout.这一点在第The Rust Reference章中进行了解释(请点击链接查看实践中的具体示例):

临时值的生存期通常是最内层的

然而,我宁愿听从谢普马斯特的建议.显式引入局部变量将帮助代码读者专注于更重要的事情,比如确保不安全的代码是正确的(而不是必须弄清楚临时变量的确切语义).

如何判断这个

您可以使用以下代码判断此行为:

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

Rust相关问答推荐

if let声明中临时对象的生存期

什么是谓词的简短和简洁类型

程序退出后只写入指定管道的数据

如何从Rust记录WASM堆内存使用情况?

如何在tauri—leptos应用程序中监听后端值的变化?""

什么样的 struct 可以避免使用RefCell?

从Rust调用C++虚拟方法即使在成功执行之后也会引发Access违规错误

为什么类型需要在这个代码中手动指定,在rust?

在自身功能上实现类似移动的行为,以允许通过大小的所有者进行呼叫(&;mut;self)?

如何指定不同的类型来常量Rust中的泛型参数?

在析构赋值中使用一些现有绑定

循环访问枚举中的不同集合

解析程序无法在Cargo 发布中 Select 依赖版本

当我try 使用 SKI 演算中的S I I实现递归时,为什么 Rust 会失败?

如何返回 struct 体中向量的切片

将 &str 或 String 保存在变量中

Rust 文件未编译到 dll 中

如何为已实现其他相关 std trait 的每个类型实现一个 std Trait

str 和 String 的 Rust 生命周期

为什么这里需要类型注解?