`if`分支具有自有和借用值,没有let绑定

我有这个if声明,其中两个分支都必须返回一个&HashMap<..>. 在其中一个分支中,虽然我拥有一个分支,而另一个分支中HashMap我正在从对某个结构的引用访问一个。目前,我被迫letif块外定义一个未绑定的变量来保存来自第一个分支的拥有的映射(否则它将在if块的末尾被释放并且引用将无效)。

struct Descriptor {
    env: HashMap<String, String>
}

fn merge_env(_a: &HashMap<..>, _b: &HashMap<..>) -> HashMap<String, String> {
    todo!()
}

fn example(d1: &Descriptor, d2: &Descriptor, feature_on: bool) {
    // Can I somehow avoid having to declare this?
    let holder;
    let env = if feature_on {
        holder = merge_env(&d1.env, &d2.env);
        &holder
    } else {
        &d1.env
    };
    read_env(&env);
}

fn read_env(_env: &HashMap<String, String>) { todo!() }

操场

有没有办法避免未绑定let?也许一些包装器可以同时保存拥有和借用的价值?另外,目前的方式是惯用的吗?

回答

变量有 Rust 的范围。一旦它们的范围结束,它们就会被取消分配。因此,如果你像这样声明你的holder内部if

if feature_on {
        let holder = merge_env(&d1.env, &d2.env);
        &holder
} 

// holder has already been dropped at that point. It would be "use after free" error to use it here

if块外使用它是不可能的,因为它会在那个时候被丢弃。因此,您必须确保拥有的对象存在足够长的时间。

可能的解决方案之一是您已经完成的操作 - 通过在if您保证持有者实例不会被解除分配之前移动拥有变量,从而避免在免费错误后使用。

另一种解决方案是使用 enum std::borrow::Cow,它有两个变体Cow::Borrowed——用于保存引用和Cow::Owned保存实际实例。这完全适合您的用例:

if feature_on {
        let holder = merge_env(&d1.env, &d2.env);
        &holder
} 

// holder has already been dropped at that point. It would be "use after free" error to use it here


以上是`if`分支具有自有和借用值,没有let绑定的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>