Rust 方便地访问原始指针的成员?

Rust 方便地访问原始指针的成员?,rust,Rust,对于我们知道不需要对照NULL检查的实例,访问原始指针的嵌套成员的表示法可能相当尴尬: struct MyLink { link: *mut MyLink, } 可以访问原始指针的结构成员而不必每次显式取消引用吗?可能通过使用诸如root.link().link().link()之类的方法,或者通过包装类型 虽然惯用的Rust可以避免这种情况,但在某些特殊情况下,它并不那么容易避免Rc有内存开销,借用检查器会导致链接成员出现问题,C-API可能需要指针。。。等等。包装器方法确实可以提高

对于我们知道不需要对照NULL检查的实例,访问原始指针的嵌套成员的表示法可能相当尴尬:

struct MyLink {
    link: *mut MyLink,
}
可以访问原始指针的结构成员而不必每次显式取消引用吗?可能通过使用诸如
root.link().link().link()
之类的方法,或者通过包装类型


虽然惯用的Rust可以避免这种情况,但在某些特殊情况下,它并不那么容易避免<代码>Rc有内存开销,借用检查器会导致链接成员出现问题,C-API可能需要指针。。。等等。

包装器方法确实可以提高代码的可读性。仅通过以下方式:

是否将方法原型标记为不安全取决于您的具体情况,但实现必须位于不安全的块中:从指针获取引用,即使不取消引用,也是不安全的

使用它:

unsafe {
    let mut l1 = MyLink {
        link: 0 as *mut MyLink,
        n: 4,
    };

    let mut l2 = MyLink {
        link: &mut l1 as *mut MyLink,
        n: 3,
    };
    let n1 = l2.n;
    let n2 = l2.link().n;
    println!("{} -> {}", n1, n2);
}

如果这是代码中经常出现的情况,我只需要创建一个通用包装器

#[repr(C)]
#[derive(Hash)]
struct Ptr<T> {
    ptr: *mut T
}

impl<T> Ptr<T> {
    pub unsafe fn new(ptr: *mut T) -> Ptr<T> {
        debug_assert!(!ptr.is_null());
        Ptr { ptr: ptr }
    }

    #[inline(always)]
    pub fn as_pointer(&self) -> *mut T {
        self.ptr
    }
}

impl<T> Deref for Ptr<T> {
    type Target = T;

    #[inline(always)]
    fn deref(&self) -> &T {
        unsafe { &*self.ptr }
    }
}

impl<T> DerefMut for Ptr<T> {
    #[inline(always)]
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.ptr }
    }
}

impl<T> Copy for Ptr<T> { }
impl<T> Clone for Ptr<T> {
    #[inline(always)]
    fn clone(&self) -> Ptr<T> { *self }
}

impl<T> PartialEq for Ptr<T> {
    fn eq(&self, other: &Ptr<T>) -> bool {
        self.ptr == other.ptr
    }
}

对于原始指针,可以采用与任何其他类型完全相同的方式实现自定义方法:

trait WickedRef<T>{
    unsafe fn wicked_ref<'x>(self) -> &'x T;
}

impl<T> WickedRef<T> for *mut T{
    unsafe fn wicked_ref<'x>(self) -> &'x T{
        &*self
    }    
}

root.link.wicked_ref().link.wicked_ref()
trait-WickedRef{

不安全的fn-wecked\u ref您是否尝试过包装器方法方法?我对edge的情况也很好奇。@E\u net4,我还没有尝试过它(不确定如何编写),但似乎是最有希望的解决方案。说“[生锈的指针]不需要检查NULL”是不正确的。引用具有该属性(不能为NULL),这就是为什么对它们应用借用检查器(以防止挂起引用)。另一方面,指针可以为null,但对它们的安全检查是,它们不能在
不安全的
块之外解除引用。@ampron非常正确。但是,我相信这个问题可以解释为“它们不必在我的用例中被检查”。为了避免混淆,我更新了问题,我的意思是在这个特殊的案例中。(可能删除最后3条注释以避免噪音)与使用原始指针相比,这会增加发布版本的开销吗?@ideasman42:在优化后,不应该这样做。这些方法非常简单,可以内联。如果您担心这一点,您可以使用slap
#[inline(always)]
deref
deref_mut
之上。太好了,这就是我的假设,我也想知道
MyLink{link:Ptr::new(1 as*mut)};
可以写得更紧凑一点,我想宏可以作为最后的手段。@ideasman42:使用构造函数接受
*mut MyLink
:)非空断言似乎没有任何实用程序;该属性不在任何地方使用,指针有非空和错误的其他方式。
#[repr(C)]
#[derive(Hash)]
struct Ptr<T> {
    ptr: *mut T
}

impl<T> Ptr<T> {
    pub unsafe fn new(ptr: *mut T) -> Ptr<T> {
        debug_assert!(!ptr.is_null());
        Ptr { ptr: ptr }
    }

    #[inline(always)]
    pub fn as_pointer(&self) -> *mut T {
        self.ptr
    }
}

impl<T> Deref for Ptr<T> {
    type Target = T;

    #[inline(always)]
    fn deref(&self) -> &T {
        unsafe { &*self.ptr }
    }
}

impl<T> DerefMut for Ptr<T> {
    #[inline(always)]
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.ptr }
    }
}

impl<T> Copy for Ptr<T> { }
impl<T> Clone for Ptr<T> {
    #[inline(always)]
    fn clone(&self) -> Ptr<T> { *self }
}

impl<T> PartialEq for Ptr<T> {
    fn eq(&self, other: &Ptr<T>) -> bool {
        self.ptr == other.ptr
    }
}
struct MyLink {
    link: Ptr<MyLink>,
}

fn main() {
    let mut link = MyLink { link: unsafe { Ptr::new(1 as *mut _) } };
    let next = MyLink { link: unsafe { Ptr::new(&mut link as *mut _) } };
    let _ = next.link;
}
trait WickedRef<T>{
    unsafe fn wicked_ref<'x>(self) -> &'x T;
}

impl<T> WickedRef<T> for *mut T{
    unsafe fn wicked_ref<'x>(self) -> &'x T{
        &*self
    }    
}

root.link.wicked_ref().link.wicked_ref()