将结构实现分配给另一个结构实现



我想在一个名为"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: &registry }
}
}
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: &registry }
|        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|        |
|        expected `&Mailer<'reg>`, found struct `Mailer`
|        help: consider borrowing here: `&Mailer { registry: &registry }`

基本上我不知道如何正确地注释返回的Mailer结构。

只需返回

&Mailer<'req> { registry: &registry }

而不是

Mailer { registry: &registry }

根本不是补救办法。

在Rust文档中,我肯定遗漏了很多关于所有权的内容。在我的辩护中,我没有发现任何关于结构实现分配其他结构实现的例子或解释。

我在这里迷路了。

您的new函数返回一个&Mailer<'_>(隐藏了生存期(,但您的最终表达式是Mailer { ... },它的类型是Mailer<'_>,而不是&Mailer<'_>,因此您会得到一个错误。

简单地让它返回&Mailer { ... }是行不通的,原因不同。

让我们想象一下这样写,相当于:

fn new() -> &'reg Mailer<'reg> {
let registry = handlebars::Handlebars::new();       
let mailer = Mailer { registry: &registry };
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的调用方

最新更新