【问题标题】:Cannot move out of dereference of `&`-pointer无法脱离 `&`-pointer 的取消引用
【发布时间】:2014-10-26 03:49:42
【问题描述】:

我有以下代码

pub struct PropertyDeclarationBlock {
    pub declarations: Arc<Vec<(PropertyDeclaration, PropertyDeclarationImportance)>>
}

impl PropertyDeclarationBlock {
    pub fn select_declarations(&self) -> Arc<Vec<PropertyDeclaration>> {
        Arc::new(self.declarations.clone().map_in_place(|p| {
                                                        let (declaration, _) = p;
                                                        declaration
                                                        }))
    }

}

我希望能够在 PropertyDeclarationBlock 上调用 .select_declarations() 并让它返回声明的克隆,但它不是 Arc Vec(PropertyDeclaration,PropertyDeclarationImportance)只是 Arc Vec PropertyDeclaration,换句话说,返回一个 PropertyDeclaration 的向量,而不是前面的元组。

前一个无法编译,因为我收到以下错误:

error: cannot move out of dereference of `&`-pointer
Arc::new(self.declarations.clone().map_in_place(|p| {
         ^~~~~~~~~~~~~~~~~~~~~~~~~

据我了解,由于该函数将 self 作为参数,因此它将拥有它的所有权。因为我宁愿使用 burrow self 函数,所以我使用 &。

编辑

这是实现新功能后的错误信息:

error: cannot move out of dereference of `&`-pointer
Arc::new(self.declarations.iter().map(|&(declaration, _)| declaration).collect())
                                       ^~~~~~~~~~~~~~~~~
note: attempting to move value to here (to prevent the move, use `ref declaration` or `ref mut declaration` to capture value by reference)
Arc::new(self.declarations.iter().map(|&(declaration, _)| declaration).collect())
                                         ^~~~~~~~~~~

我尝试按照错误消息的建议在声明之前应用 ref 关键字,但没有帮助。

【问题讨论】:

    标签: rust


    【解决方案1】:

    self.declarations.clone() 克隆 Arc,而我相信您打算克隆 Vec。为了解决对map_in_place 的调用,编译器会自动取消对Arc 的引用,以便能够调用在Vec 上定义的方法。编译器知道如何取消引用Arc,因为Arc 实现了Derefderef 返回一个借来的指针,这就是错误的来源。要克隆Vec,我们必须显式取消引用Arc(*self.declarations).clone()

    但是,map_in_place 在这种情况下不适合,因为(PropertyDeclaration, PropertyDeclarationImportance) 的大小与PropertyDeclaration 的大小不同(除非PropertyDeclarationImportance 的大小为零,这可能不是这种情况),这每个文档都需要。它失败并显示类似以下的消息:

    task '<main>' failed at 'assertion failed: mem::size_of::<T>() == mem::size_of::<U>()', /build/rust-git/src/rust/src/libcollections/vec.rs:1805
    

    这是一个正确的实现:

    impl PropertyDeclarationBlock {
        pub fn select_declarations(&self) -> Arc<Vec<PropertyDeclaration>> {
            Arc::new(self.declarations.iter().map(|&(declaration, _)| declaration).collect())
        }
    }
    

    在这里,我们在Vec 上使用iter 在向量的项上创建一个迭代器。这会返回一个Items,它在不可变引用上实现Iterator

    然后,我们使用map(PropertyDeclaration, PropertyDeclarationImportance) 延迟映射到PropertyDeclaration。注意我们如何解构元组闭包参数列表中的引用(这也适用于fns)而不是使用let 语句。

    最后,我们使用collect 为这个序列创建一个新的收集容器。 collect 的结果是通用的;它可以是任何实现FromIterator 的类型。 Vec 实现了FromIterator,编译器从方法的签名中推断出Vec

    【讨论】:

    • 感谢您的详尽回答。我仍然收到类似的错误。我将使用新的错误消息编辑我的问题。
    • 我在 play.rust-lang.org 上没有收到此错误。尝试获取更新的版本;关闭最近发生了变化。
    • 我正在为 Servo 编写拉取请求。 Rust 的版本由 Servo 修复。我会检查它使用的是什么版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 2018-10-31
    • 1970-01-01
    • 1970-01-01
    • 2013-09-16
    相关资源
    最近更新 更多