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