我有一个特性 Foo
pub trait Foo {
fn do_something(&self) -> f64;
}
以及引用该trait的结构体
pub struct Bar {
foo: Foo,
}
尝试编译时我收到以下错误信息:
error: reference to trait `Foo` where a type is expected; try `Box<Foo>` or `&Foo`
将结构体更改为
struct Bar {
foo: &Foo,
}
告诉我 error: missing lifetime specifier
将定义更改为
struct Bar {
foo: Box<Foo>,
}
编译成功——耶!
但是,当我想让一个函数在bar
时返回foo
,类似于:
impl Bar {
fn get_foo(&self) -> Foo {
self.foo
}
}
显然 bar.foo
是一个 Box<Foo>
,因此我得到了 error: reference to trait `Foo` where a type is expected; try `Box<Foo>` or `&Foo`
的错误提示。
将签名更改为:
impl Bar {
fn get_foo(&self) -> Box<Foo> {
let this = *self;
this.foo
}
}
但是现在当我尝试对self
进行解引用时,会出现错误:无法移动`&`指针的解引用
。
更改为
impl Bar {
fn get_foo(self) -> Box<Foo> {
self.foo
}
}
一切都很好。
那么...
- 为什么
bar
结构体中的&
不起作用?我猜想我们必须将其包装成指向特质的指针(因为我们无法知道它的大小),这样才能保证结构体有一个固定的内存布局,但是编译器为什么会建议一些不能编译的代码呢? - 为什么我不能在
get_foo()
中取消引用self
- 所有我看到的示例都使用了借用的self
语法? - 去掉
&
直接使用self
的影响是什么?
学习Rust很有趣,但内存安全既让人着迷又令人生畏!
完整可编译代码:
trait Foo {
fn do_something(&self) -> f64;
}
struct Bar {
foo: Box<Foo>,
}
impl Bar {
fn get_foo(self) -> Box<Foo> {
let foo = self.foo;
foo.do_something();
foo
}
}
fn main() {}
foo: &'a Foo
和foo: Box<Foo>
,这些变化的原因是什么? - nhaarman