'&&x' 模式匹配是否会导致 x 被复制? [英] Does a '&&x' pattern match cause x to be copied?

查看:43
本文介绍了'&&x' 模式匹配是否会导致 x 被复制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

std 的文档中:iter::Iterator::filter() 它解释了值是通过引用传递给闭包的,并且由于许多迭代器产生引用,在这种情况下传递的值是对引用的引用.它通过使用 &x 模式删除一级间接,或使用 &&x 模式删除二级间接,提供了一些改进人体工程学的建议.

然而,我发现如果被迭代的项目没有实现Copy,则第二个模式不会编译:

#[derive(PartialEq)]结构 Foo(i32);fn 主(){让 a = [Foo(0), Foo(1), Foo(2)];//这有效让 _ = a.iter().filter(|&x| *x != Foo(1));//这也有效让 _ = a.iter().filter(|&x| x != &Foo(1));//这不会编译让 _ = a.iter().filter(|&&x| x != Foo(1));}

你得到的错误是:

错误[E0507]:无法移出共享引用-->src/main.rs:14:30|14 |让 _ = a.iter().filter(|&&x| x != Foo(1));|^^-|||||数据移到这里||移动发生是因为 `x` 具有类型 `Foo`,它没有实现 `Copy` 特性|帮助:考虑删除`&`:`&x`

这是否意味着如果我使用 &&x 解构模式,并且值为 Copy,Rust 会默默地复制我正在迭代的每个值?如果是这样,为什么会发生这种情况?

解决方案

在 Rust 中,函数或闭包参数是无可辩驳的模式.

Rust 参考 中,它说:<块引用>

默认情况下,标识符模式将变量绑定到副本或移动从匹配的值取决于匹配的值实现复制.

所以,在这种情况下:

let _ = a.iter().filter(|&x| *x != Foo(1));

闭包被传递一个对被迭代项的引用的引用;因此 x 绑定到项目引用的副本.你总是可以复制一个引用(它基本上是一个无操作)所以这总是成功的.

在这种情况下:

let _ = a.iter().filter(|&&x| x != Foo(1));

x 绑定到项目本身的副本 - 如果项目不是 Copy,则失败.

参考文献还说:

<块引用>

这可以更改为使用 ref 关键字绑定到引用,或使用 ref mut 的可变引用.

虽然在这种情况下这不是很有用:&&ref x 导致 x 是对项目的引用,就像您使用了 &x.

In the documentation for std::iter::Iterator::filter() it explains that values are passed to the closure by reference, and since many iterators produce references, in that case the values passed are references to references. It offers some advice to improve ergonomics, by using a &x pattern to remove one level of indirection, or a &&x pattern to remove two levels of indirection.

However, I've found that this second pattern does not compile if the item being iterated does not implement Copy:

#[derive(PartialEq)]
struct Foo(i32);

fn main() {
    let a = [Foo(0), Foo(1), Foo(2)];

    // This works
    let _ = a.iter().filter(|&x| *x != Foo(1));

    // This also works
    let _ = a.iter().filter(|&x| x != &Foo(1));

    // This does not compile
    let _ = a.iter().filter(|&&x| x != Foo(1));
}

The error you get is:

error[E0507]: cannot move out of a shared reference
  --> src/main.rs:14:30
   |
14 |     let _ = a.iter().filter(|&&x| x != Foo(1));
   |                              ^^-
   |                              | |
   |                              | data moved here
   |                              | move occurs because `x` has type `Foo`, which does not implement the `Copy` trait
   |                              help: consider removing the `&`: `&x`

Does this mean that if I use the &&x destructuring pattern, and the value is Copy, Rust will silently copy every value I am iterating over? If so, why does that happen?

解决方案

In Rust, function or closure arguments are irrefutable patterns.

In the Rust reference, it says:

By default, identifier patterns bind a variable to a copy of or move from the matched value depending on whether the matched value implements Copy.

So, in this case:

let _ = a.iter().filter(|&x| *x != Foo(1));

the closure is being passed a reference to a reference to the item being iterated; therefore x is bound to a copy of a reference to the item. You can always copy a reference (it is basically a no-op) so this always succeeds.

In this case:

let _ = a.iter().filter(|&&x| x != Foo(1));

x is being bound to a copy of the item itself - which fails if the item is not Copy.

The reference also says:

This can be changed to bind to a reference by using the ref keyword, or to a mutable reference using ref mut.

That's not so useful in this case though: &&ref x results in x being a reference to the item, the same as if you had used &x.

这篇关于'&amp;&amp;x' 模式匹配是否会导致 x 被复制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆