在 Rust 中指向临时对象的原始指针可以吗? [英] Are raw pointers to temporaries ok in Rust?

查看:32
本文介绍了在 Rust 中指向临时对象的原始指针可以吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个这样的功能:

extern {
    fn foo(layout: *const RawLayout) -> libc::uint8_t;
}

fn bar(layout: Layout) -> bool {
    unsafe {
        foo(&layout.into() as *const _) != 0
    }
}

其中 Layout 是可复制的类型,可以将 .into() 转换为 RawLayout.

Where Layout is a copyable type that can be converted .into() a RawLayout.

我想确保我了解正在发生的事情,因为这是不安全的.据我了解,layout.into() 创建一个临时的 RawLayout,然后 & 引用它,as*const _ 将其转换为原始指针 (*const RawLayout).然后foo()函数被调用并返回,最后临时的RawLayout被删除.

I want to make sure I understand what is happening as it is unsafe. As I understand it, layout.into() creates a temporary RawLayout, then & takes a reference to it, and as *const _ converts it to a raw pointer (*const RawLayout). Then the foo() function is called and returns, and finally the temporary RawLayout is dropped.

这样对吗?或者有什么棘手的理由为什么我不应该这样做?

Is that correct? Or is there some tricky reason why I shouldn't do this?

推荐答案

你说得对.在这种情况下,首先调用 foo,然后删除 RawLayout.这在 The Rust Reference 中有解释(点击链接查看具体这在实践中如何运作的示例):

You are right. In this case, foo is called first and RawLayout is dropped afterwards. This is explained in The Rust Reference (follow the link to see concrete examples of how this works out in practice):

临时值的生命周期通常是最内层的封闭声明

The lifetime of temporary values is typically the innermost enclosing statement

不过,我更愿意听从 Shepmaster 的建议.显式引入局部变量将有助于代码的读者专注于更重要的事情,例如确保不安全代码是正确的(而不必弄清楚临时变量的确切语义).

However, I would rather follow Shepmaster's advice. Explicitly introducing a local variable would help the reader of the code concentrate in more important things, like ensuring that the unsafe code is correct (instead of having to figure out the exact semantics of temporary variables).

您可以使用以下代码来检查此行为:

You can use the code below to check this behavior:

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 中指向临时对象的原始指针可以吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆