首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么Pin::new_unchecked(&self)有效,而Pin::new_unchecked(&self).as_ref()不行?

为什么Pin::new_unchecked(&self)有效,而Pin::new_unchecked(&self).as_ref()不行?
EN

Stack Overflow用户
提问于 2021-06-16 18:37:11
回答 1查看 45关注 0票数 1

我正在编写一个引用内存映射堆栈上分配的变量的StackBox,并实现了Drop特征,以便可以将StackBox用作引用。

因为我可以保证如果StackBox是由我的代码创建的,那么内存映射堆栈一定不能被修改,所以我决定添加返回Pin<&T>pin方法。

然而,我发现奇怪的是,Pin::new_unchecked(&self)可以工作,但Pin::new_unchecked(&self).as_ref()不能工作。

下面是StackBox的完整代码

代码语言:javascript
复制
pub struct StackBox<'a, T> {                      
    ptr: *mut T,                                  
    phantom: PhantomData<&'a T>,                  
}                                                 
impl<'a, T> StackBox<'a, T> {                     
    fn new(ptr: *mut T) -> StackBox<'a, T> {      
        StackBox {                                
            ptr,                                  
            phantom: PhantomData                  
        }                                         
    }                                             
    /// Why does this compile?
    /// Pin::new_unchecked(&self).as_ref() doesn't work here
    pub fn pin(&self) -> Pin<&T> {                
        unsafe { Pin::new_unchecked(&self) }      
    }                                             
}                                                 
impl<'a, T> Drop for StackBox<'a, T> {            
    fn drop(&mut self) {                          
        unsafe {                                  
            self.ptr.drop_in_place();             
        }                                         
    }                                             
}                                                 
impl<'a, T> Deref for StackBox<'a, T> {           
    type Target = T;                              
                                                  
    fn deref(&self) -> &Self::Target {            
        unsafe { & *self.ptr }                    
    }                                             
}                                                 
impl<'a, T> DerefMut for StackBox<'a, T> {        
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe { &mut *self.ptr }                 
    }                                             
}                                                 
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-06-16 23:36:28

当您编写Pin::new_unchecked(&self)时,您可能指的是Pin::new_unchecked(self),因为self已经是一个引用,但分析基本上是相同的:

代码语言:javascript
复制
    pub fn pin(&self) -> Pin<&T> {
        unsafe { Pin::new_unchecked(self) }
    }

您可能在想,您正在创建一个Pin<&StackBox<T>>,然后它会神奇地转换为一个Pin<&T>

但这并不是真正发生的事情。它实际上是从返回类型推导出函数调用的类型,所以您调用的是Pin::<&T>::new_unchecked(),在此调用中,通过使用下面实现的deref()self被转换为&T。这就好像是:

代码语言:javascript
复制
    pub fn pin(&self) -> Pin<&T> {                
        unsafe { Pin::<&T>::new_unchecked(self.deref()) }
    }                                             

这可以更明显地写成:

代码语言:javascript
复制
    pub fn pin(&self) -> Pin<&T> {                
        unsafe { Pin::new_unchecked(&*self.ptr) }
    }                                             

至于为什么带有as_ref()的版本不能工作,这是因为您的self&StackBox<T>,而不是StackBox<T>。例如,as_ref()对于移除智能指针层很有用,因此它可以将Pin<Box<T>>转换为Pin<&T>。但如果您从Pin<&Box<T>>开始(这没有太多意义),就不需要进行转换。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68001056

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档