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

Gre*_*olm 10 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();
}
Run Code Online (Sandbox Code Playgroud)

这当然无法使用此错误进行编译:

pointers.rs:11:8: 11:21 error: cannot move out of dereference of & pointer
pointers.rs:11         self.thingies
Run Code Online (Sandbox Code Playgroud)

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

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

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

A.B*_*.B. 13

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

复制解决方案

struct Widget {
  thingies: ~[int]
}

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

    fn somethings(&self) -> ~[int] {
        self.thingies.clone()
    }
}
Run Code Online (Sandbox Code Playgroud)

参考方案

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
    }
}
Run Code Online (Sandbox Code Playgroud)

切片解决方案

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()
    }
}
Run Code Online (Sandbox Code Playgroud)

要理解引用和切片解决方案,您需要了解其'a含义:它表示生命周期,并且&'a是一种告诉编译器引用必须永远不会超过它引用的对象的方法,在这种情况下,它是一个Widget.

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

如果你返回一个可变引用,你当然可以修改thingies.将编写具有生命周期的可变引用&'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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

编辑:删除冗余生命周期声明.


Pao*_*lla 7

=== 编辑 ===

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

Rust的所有权模式对语言来说非常重要,因此有关更多信息,我建议查看有关所有权借用的优秀官方文档

=== 结束编辑 ===

在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
Run Code Online (Sandbox Code Playgroud)

您可以借用对thingies的引用:

fn somethings<'a>(&'a self) -> &'a~[int] {
    &self.thingies
}
Run Code Online (Sandbox Code Playgroud)

或明确返回一些东西

fn somethings(&self) -> ~[int] {
    self.thingies.clone()
}
Run Code Online (Sandbox Code Playgroud)