如何从函数返回拥有的数组?

时间:2014-01-23 13:11:05

标签: arrays rust rust-0.8

我是一个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

3 个答案:

答案 0 :(得分:11)

您的代码无法编译的原因是唯一指针~只能拥有一个所有者。编译器阻止您编写容易出错的代码。你可以决定返回一个东西的副本,一个对东西的引用,或一片东西(它是对矢量数据或它的一部分的引用)。

复制解决方案

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是一种告诉编译器引用必须永远不会超过它引用的对象的方法,在这种情况下是一个小工具。

这些解决方案也有一些限制:您无法修改当前引用的对象,因为这样做会使引用变为无效。

如果您返回可变引用,您当然可以修改内容。具有生命周期的可变引用将被写为&'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中写了这个。

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

答案 1 :(得分:7)

=== 编辑 ===

在Rust 1稳定版中,~[T]变为Vec<T>,但(语法旁边)同样的问题也适用,因为Vec仍然拥有唯一的所有者。简而言之,somethings仅提及自我和(通过引用)它不能成为thingies的所有者。这里有Rust 1版本的游乐场链接:https://play.rust-lang.org/?gist=50ec1acdc684e53fd5f9&version=stable

Rust的所有权模式对语言非常重要,因此有关更多信息,我建议您查看有关ownershipborrowing

的优秀官方文档

=== END EDIT ===

在Rust中,.之后self自动取消引用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

你可以借用对thingies的引用:

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

或明确返回thingies的副本

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

答案 2 :(得分:2)

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

struct Widget {
    thingies: ~[int]
}

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