Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 需要引用时有条件地克隆_Rust - Fatal编程技术网

Rust 需要引用时有条件地克隆

Rust 需要引用时有条件地克隆,rust,Rust,我有一个对结构的引用 我需要一个结构的引用。有时是一样的,但有时是克隆的,然后是修改的 现在,我知道了 if condition { let mut copy = original.clone(); copy.select(); do_big_thing(&copy); } else { do_big_thing(original); } 但是do\u big\u thing接受其他参数,我不想重复这一行 有办法去吗 首先构建引用,该引用可以是原始引用

我有一个对结构的引用

我需要一个结构的引用。有时是一样的,但有时是克隆的,然后是修改的

现在,我知道了

if condition {
    let mut copy = original.clone();
    copy.select();
    do_big_thing(&copy);
} else {
    do_big_thing(original);
}
但是
do\u big\u thing
接受其他参数,我不想重复这一行

有办法去吗

  • 首先构建引用,该引用可以是原始引用,也可以是对本地修改克隆的引用
  • 然后在“做大事”中使用它(它不必活得更长)
?

当然,这不起作用,因为
copy
的寿命不够长:

let mut reference = if condition {
    let mut copy = original.clone();
    copy.select();
    &copy
} else {
    original
};
do_big_thing(reference);
由于这个问题是关于寻找一种更干净、更不杂乱的方法来编写相同的东西(使用原始引用或克隆),我不能接受一种会在运行时增加开销或不安全的解决方案

您可以使用来提取借来或拥有的价值:

fn do_big_thing(b: Cow<Big>, a: usize) {
    println!("{}", a + b.c);
}

fn do_huge_thing(original: &Big, a: usize, condition: bool) {
    if condition {
        let mut copy = original.clone();
        copy.select();
        do_big_thing(Cow::Owned(copy), a);
    } else {
        do_big_thing(Cow::Borrowed(original), a);
    }
}

正如所示,这是经过优化的。

由于您不打算从函数返回值(如中所示),因此不需要使用
Cow
。相反,您可以在条件外声明
copy
变量:

fn do_huge_thing_stack(original: &Big, a: usize, condition: bool) {
    let mut copy;

    let r = if condition {
        copy = original.clone();
        copy.select();
        &copy
    } else {
        original
    };

    do_big_thing(r, a);
}
编译器将确保仅当值有效时才获取引用。我认为,这将生成与
Cow
版本相同的程序集,但这仍然是一项有用的技术

另见:


奶牛是一种动物。我们现在有两个测试,而不是一个测试。或者编译器能够简化这一点吗?如果有理由认为编译器可以删除第二个测试,请记住答案中的信息部分。@WesleyWiser Zero cost abstractions不是关于优化的代码,而是关于你不需要为一个功能支付更多的钱,而这是你手边做的东西。如果您使用了Cow的功能,它会增加开销。然而,这里我们并没有真正使用它的特性,而是使用它的逻辑,编译器能够看到并消除开销,但这不是零成本,只是优化,你不能期望编译器能够在每一个CoW上都这样做。但是,当你不真正使用像奶牛一样的特征时,你可以期待它here@DenysSéguret CoW是ZCA,但不是“免费的”;)ZCA并不意味着“编译为零汇编”,它意味着它不会比您自己从头开始编写它带来额外的开销。在Rust中,枚举、结构和函数通常是ZCA。据我所知,
Cow
是一个ZCA。它的实现完全符合您的期望,仅此而已@你能提供一个不是ZCA的例子吗?但是。。。这是允许的吗?这确实是我想要做的,但我不知道可以定义一个没有值的变量。@DenysSéguret并注意,这种编码模式不要求
copy
是可变的。我们只需要
mut
,因为
select
需要它。你只需要对你的代码做一点小改动:@SvenMarnach这是shep的答案。是的,这很简单,但我不知道这是允许的。这里有两个很好的答案,由于编译器的优化,这两个答案都是零成本的。我建议未来的读者看看这两个答案。
fn do_huge_thing_stack(original: &Big, a: usize, condition: bool) {
    let mut copy;

    let r = if condition {
        copy = original.clone();
        copy.select();
        &copy
    } else {
        original
    };

    do_big_thing(r, a);
}