Что я должен сделать, чтобы время жизни в итераторе работало, когда компилятор предлагает использовать ключевое слово move? - PullRequest
0 голосов
/ 23 октября 2018

У меня есть фрагмент кода, который не компилируется:

struct A {
    x: [u32; 10],
}

impl A {
    fn iter<'a>(&'a self) -> impl Iterator<Item = u32> + 'a {
        (0..10).map(|i| self.x[i])
    }
}

fn main() {}

( детская площадка )

Компилятор говорит:

error[E0373]: closure may outlive the current function, but it borrows `self`, which is owned by the current function
 --> src/main.rs:7:21
  |
7 |         (0..10).map(|i| self.x[i])
  |                     ^^^ ---- `self` is borrowed here
  |                     |
  |                     may outlive borrowed value `self`
help: to force the closure to take ownership of `self` (and any other referenced variables), use the `move` keyword
  |
7 |         (0..10).map(move |i| self.x[i])
  |                     ^^^^^^^^

Что я должен сделать, чтобы сделать эту работу?Мне нужно self позже, поэтому я не могу переместить его, как предлагает компилятор.

Редактировать : Я полагал, что move создаст проблемы при использовании self позже.Например, см. Код:

struct A {
    x: [u32; 3],
}

impl A {
    fn iter<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
        (0..3).filter(move |&i| self.x[i] != 0).map(move |i| self.x[i])
    }
}

fn main() {
    let a = A { x : [0, 1, 2]};
    for el in a.iter() {
        println!("{}", el);
    }
}

( детская площадка )

Здесь &'a self перемещается дважды, так что в действительности оба затвора стали собственниками&'a self.Код на самом деле компилируется, но я не ожидал, что после его перемещения переменная больше не будет использоваться.В книге ( соответствующий раздел ) также приведен пример, подтверждающий мое понимание:

fn main() {
    let x = vec![1, 2, 3];
    let equal_to_x = move |z| z == x;
    println!("can't use x here: {:?}", x);
    let y = vec![1, 2, 3];
    assert!(equal_to_x(y));
}

Этот код не компилируется.Почему мой код итератора работает с move?

1 Ответ

0 голосов
/ 23 октября 2018

Похоже, что компилятор уже говорит вам, что делать:

help: to force the closure to take ownership of `self` (and any other referenced variables), use the `move` keyword
  |
7 |         (0..10).map(move |i| self.x[i])
  |                     ^^^^^^^^

Ключевое слово move дает право собственности на любую захваченную переменную для замыкания.

Здесь вызахватывает ссылку self движением, а не сам объект.Вы не можете использовать объект, вызвав метод iter, потому что он принимает ваш объект не по ходу, а по ссылке.Вы можете по-прежнему использовать свой объект после вызова iter() для экземпляра.

...