11

我是一个 Rust 新手,试图通过玩它来找出语言。我在尝试从函数返回数组时遇到了一些问题:

struct Widget {
  thingies: ~[int]
}

impl Widget {
    fn new() -> Widget {
        Widget { thingies: ~[4, 8, 15, 16, 23, 42] }
    }

    fn somethings(&self) -> ~[int] {
        self.thingies
    }
}

fn main() {
   let widget = Widget::new();
   let wotsits = widget.somethings();
}

这当然会因以下错误而导致编译失败:

pointers.rs:11:8: 11:21 error: cannot move out of dereference of & pointer
pointers.rs:11         self.thingies

如果此代码示例看起来不正确,我要做的就是从已实现的结构中拉出一个数组。借来的指针并不重要,这只是我试图存储数据的方式。

关于如何正确提取我的数组的任何提示?

顺便说一句,我正在使用 Rust 0.8

4

3 回答 3

14

您的代码无法编译的原因是唯一指针~只能有一个所有者。编译器会阻止您编写容易出错的代码。您可以决定返回 thingies 的副本、对 thingies 的引用或 thingies 的切片(这是对矢量数据或其片段的引用)。

复制解决方案

struct Widget {
  thingies: ~[int]
}

impl Widget {
    fn new() -> Widget {
        Widget { thingies: ~[4, 8, 15, 16, 23, 42] }
    }

    fn somethings(&self) -> ~[int] {
        self.thingies.clone()
    }
}

参考解决方案

struct Widget {
  thingies: ~[int]
}

impl Widget {
    fn new() -> Widget {
        Widget { thingies: ~[4, 8, 15, 16, 23, 42] }
    }

    fn somethings<'a>(&'a self) -> &'a~[int] {
        &self.thingies
    }
}

切片解决方案

struct Widget {
  thingies: ~[int]
}

impl Widget {
    fn new() -> Widget {
        Widget { thingies: ~[4, 8, 15, 16, 23, 42] }
    }

    fn somethings<'a>(&'a self) -> &'a[int] {
        self.thingies.as_slice()
    }
}

要理解引用和切片解决方案,您需要了解什么'a意思:它表示生命周期,并且&'a是一种告诉编译器引用绝不能超过它引用的对象(在本例中是 Widget)的方法。

这些解决方案也有一些限制:您不能修改您当前正在引用的对象,因为这样做会导致引用变得无效。

如果您返回可变引用,您当然可以修改事物。将写入具有生命周期的可变引用&'a mut T

struct Widget {
  thingies: ~[int]
}

impl Widget {
    fn new() -> Widget {
        Widget { thingies: ~[4, 8, 15, 16, 23, 42] }
    }

    fn somethings<'a>(&'a mut self) -> &'a mut ~[int] {
        &mut self.thingies
    }
}

请注意,我相信在 Rust 0.8 中,您需要编写&'self而不是&'a因为尚不支持具有自定义名称的生命周期。我也在 0.9 中写了这个。

编辑:删除了多余的生命周期声明。

于 2014-01-23T14:04:44.160 回答
8

===编辑===

在 Rust 1 stable 中,~[T]变成Vec<T>了 ,但是(除了语法)同样的问题适用,因为 Vec 仍然有一个唯一的所有者。简而言之,somethings只有对 self 的引用,并且(通过引用)它不能成为thingies. 此处指向 Rust 1 版本的 Playground 链接:https ://play.rust-lang.org/?gist=50ec1acdc684e53fd5f9&version=stable 。

Rust 的所有权模型是该语言的核心,因此有关更多信息,我建议查看有关所有权借用的优秀官方文档

===结束编辑===

在 Rust 中,.after self, auto-dereferences self,所以这就是dereference of & pointer错误提到的。

现在,事物的所有权是您cannot move out of取消引用的部分:

   let widget = Widget::new(); // widget owns the unique pointer to self
   let wotsits = widget.somethings(); // if this worked, ownership of 
                                      // unique pointer to thingies would be
                                      // moved to wotsits

您可以借用对事物的引用:

fn somethings<'a>(&'a self) -> &'a~[int] {
    &self.thingies
}

或明确返回一份东西的副本

fn somethings(&self) -> ~[int] {
    self.thingies.clone()
}
于 2014-01-23T13:54:23.150 回答
2

正如其他答案中所解释的,您不能移出借来的指针。但是您可以通过self值或拥有的指针传递,然后您将能够返回拥有的向量:

struct Widget {
    thingies: ~[int]
}

impl Widget {
    fn somethings(self) -> ~[int] {
        self.thingies
    }
}
于 2014-01-23T15:02:18.967 回答