为我们知道不需要检查NULL的实例访问原始指针的嵌套成员的符号可能相当尴尬:
struct MyLink {
link: *mut MyLink,
}
let var = *(*(*(*root).link).link).link;
是否可以访问原始指针的结构成员而无需每次都明确地取消引用?也许通过使用像root.link().link().link()
这样的方法或者包装类型?
虽然习惯性的Rust避免了这种情况,但在特殊情况下,它并不容易避免。 Rc
有内存开销,借用检查器会导致链接成员出现问题,C-API可能需要指针等等。
答案 0 :(得分:3)
如果这是代码中的重复出现的情况,我只想创建一个通用的包装器。
connect_args={ "cursor_factory": MyCursor }
我们在构造时声明#[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
}
}
实际上不是null,因此我们不必在解除引用时再次检查。
然后我们在调用方法或访问属性时让语言检查ptr
/ Deref
:
DerefMut
答案 1 :(得分:1)
包装器方法确实可以提高该代码的可读性。只需按照The Book:
struct MyLink {
link: *mut MyLink,
pub n: i32,
}
impl MyLink {
pub unsafe fn link(&self) -> &MyLink {
&*self.link
}
pub unsafe fn mut_link(&mut self) -> &mut MyLink {
&mut *self.link
}
}
是否将方法原型标记为unsafe
取决于您的具体情况,但实现必须位于不安全的块中:即使没有解除引用,从指针获取引用也是不安全的。< / p>
使用它:
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);
}
答案 2 :(得分:1)
您可以使用与任何其他Rust类型完全相同的方式为原始指针实现自定义方法:
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()