我是一个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答案 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的所有权模式对语言非常重要,因此有关更多信息,我建议您查看有关ownership和borrowing
的优秀官方文档=== 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
}
}