我想在一个名为"Mailer";。
该实例将在运行";新的";Mailer实现的功能。
我确实在弄清楚每个范围的正确所有权方面遇到了巨大的问题。
use handlebars::Handlebars;
pub struct Mailer<'reg> {
registry: &'reg handlebars::Handlebars<'reg>
}
impl <'reg>Mailer<'reg> {
pub fn new() -> &'reg Mailer<'reg> {
let registry = handlebars::Handlebars::new();
Mailer { registry: ®istry }
}
}
fn main() -> Result<(), std::io::Error> {
let mailer = Mailer::new();
Ok(())
}
编译器出现以下错误:
error[E0308]: mismatched types
--> src/utils/mailer.rs:9:8
|
8 | pub fn new() -> &'reg Mailer<'reg> {
| ------------------ expected `&'reg Mailer<'reg>` because of return type
...
9 | Mailer { registry: ®istry }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| expected `&Mailer<'reg>`, found struct `Mailer`
| help: consider borrowing here: `&Mailer { registry: ®istry }`
基本上我不知道如何正确地注释返回的Mailer结构。
只需返回
&Mailer<'req> { registry: ®istry }
而不是
Mailer { registry: ®istry }
根本不是补救办法。
在Rust文档中,我肯定遗漏了很多关于所有权的内容。在我的辩护中,我没有发现任何关于结构实现分配其他结构实现的例子或解释。
我在这里迷路了。
您的new
函数返回一个&Mailer<'_>
(隐藏了生存期(,但您的最终表达式是Mailer { ... }
,它的类型是Mailer<'_>
,而不是&Mailer<'_>
,因此您会得到一个错误。
简单地让它返回&Mailer { ... }
是行不通的,原因不同。
让我们想象一下这样写,相当于:
fn new() -> &'reg Mailer<'reg> {
let registry = handlebars::Handlebars::new();
let mailer = Mailer { registry: ®istry };
return &mailer;
}
在Rust中,将某些数据的所有权从函数传递给调用者的唯一方法是返回它。例如,如果我在函数中创建了一个Vec
,并且我想将所有权传递给调用者,我必须返回它:
fn make_vec() -> Vec<i32> {
vec![1, 2, 3]
}
调用代码拥有vec的所有权,因此负责丢弃它
回到你的代码,你正在创建一个Mailer
,但你没有将它返回给调用者,你只是返回了对它的引用。所有权保留在new
内部,因此new
负责删除它。
当函数返回时,mailer
会被丢弃,因为它已经到达了声明它的范围的末尾,但我们保留了对它的引用(通过将它返回给调用者(。这是不允许的,因为它允许在释放后使用(在删除某些数据后使用对该数据的引用(。
我以前没有在Rust中使用过车把,但你可能想把你的代码改成这样:
struct Mailer<'reg> {
registry: handlebars::Handlebars<'reg> // no reference here
}
impl<'reg> Mailer<'reg> {
fn new() -> Self {
let registry = handlebars::Handlebars::new();
Self { registry } // shorthand for Self { registry: registry }
}
}
关键区别在于:
Mailer
采用拥有的Handlebars
实例,而不是引用一个实例new
返回拥有的Mailer
通过这种方式,将全部所有权传递给Mailer::new
的调用方