2015-05-29 15 views
6

Tôi cho rằng câu hỏi này là về tuổi thọ nói chung, nhưng tôi gặp khó khăn với đóng cửa đặc biệt vì bạn không thể viết ra loại của họ.Làm thế nào để khai báo một đóng cửa tồn tại lâu hơn khối bao quanh của nó

Ví dụ này hơi bị lôi cuốn - Tôi chỉ mới bắt đầu học Rust, và đây là thứ tôi đã bị treo lên.

Chương trình này sẽ không biên dịch:

fn main() { 
    let mut list: Vec<&Fn() -> i32> = Vec::new(); 

    { 
     list.push(&|| 1); 
    } 
} 

Bởi vì:

src/main.rs:5:25: 5:24 error: borrowed value does not live long enough 
src/main.rs:5   list.push(&|| 1); 
           ^~~~ 
src/main.rs:2:50: 7:2 note: reference must be valid for the block suffix following statement 0 at 2:49... 
src/main.rs:2  let mut list: Vec<&Fn() -> i32> = Vec::new(); 
src/main.rs:3 
src/main.rs:4  { 
src/main.rs:5   list.push(&move || 1); 
src/main.rs:6  } 
src/main.rs:7 } 
src/main.rs:5:9: 5:26 note: ...but borrowed value is only valid for the statement at 5:8 
src/main.rs:5   list.push(&|| 1); 
         ^~~~~~~~~~~~~~~~~ 
src/main.rs:5:9: 5:26 help: consider using a `let` binding to increase its lifetime 
src/main.rs:5   list.push(&|| 1); 
         ^~~~~~~~~~~~~~~~~ 

Những gì tôi thu thập từ các lỗi này là tuổi thọ của việc đóng cửa được giới hạn trong tuyên bố bên trong khối, nhưng nó cần phải sống cho toàn bộ cơ thể của main.

Tôi biết (hoặc, tôi nghĩ) rằng việc chuyển phần đóng thành push làm tham chiếu có nghĩa là push chỉ mượn khoản đóng và quyền sở hữu đó sẽ được trả về khối. Mã này sẽ hoạt động nếu tôi chỉ có thể đóng cửa cho push (tức là nếu push sở hữu đóng cửa), nhưng do đóng cửa không có kích thước, tôi phải chuyển nó làm tài liệu tham khảo.

Đúng không? Làm thế nào tôi có thể làm cho mã này hoạt động?

Trả lời

8

Có hai điều bạn đang yêu cầu về:

  1. xác định một typename kiếm cái gì đó không có typename specifyable
  2. để cho một đóng cửa sống lâu hơn khối nơi nó được định nghĩa.

Vấn đề đầu tiên được khắc phục bằng cách KHÔNG chỉ định tên tệp và cho phép suy luận kiểu của công việc làm gỉ.

let mut list: Vec<_> = Vec::new(); 

Vấn đề thứ hai là cố định bằng cách không cố gắng để làm việc đóng cửa sống lâu hơn, nhưng bằng cách làm cho nó "bởi giá trị", do đó bạn có thể di chuyển nó. Điều này thực thi rằng việc đóng của bạn không tham chiếu bất cứ điều gì, nhưng sở hữu tất cả các giá trị đã capture.

for i in 0..10 { 
    list.push(move || i); 
} 

Bây giờ điều này mang lại cho chúng tôi một vấn đề mới. Nếu chúng tôi thêm một đóng cửa khác vào Vec, các loại sẽ không khớp. Do đó để đạt được điều đó, chúng ta cần phải đóng hộp.

fn main() { 
    let mut list: Vec<Box<Fn() -> i32>> = Vec::new(); 

    for i in 0..10 { 
     list.push(Box::new(move|| i)); 
    } 

    { 
     list.push(Box::new(move|| 42)); 
    } 
} 
6

Borrows không sở hữu điều họ trỏ đến. Vấn đề của bạn là bạn đang mượn tạm thời sẽ ngừng tồn tại ngay sau khi nó được mượn vì bạn chưa lưu trữ ở bất cứ đâu. Nếu có ích, hãy xem xét rằng khách hàng vay không mượn các giá trị, họ mượn bộ nhớ và tạm thời chỉ có bộ nhớ tạm thời.

Nếu bạn muốn mượn một thứ gì đó để kéo dài trong bất kỳ khoảng thời gian cụ thể nào, bạn phải mượn từ bộ nhớ sẽ kéo dài ít nhất. Trong trường hợp này, vì bạn muốn lưu trữ khoản vay theo số Vec, điều này có nghĩa là bất kỳ dung lượng nào bạn mượn phải cũng sống ngoài số Vec cũng như. Như vậy:

fn main() { 
    let closure; 
    let mut list: Vec<&Fn() -> i32> = Vec::new(); 

    { 
     closure = || 1; 
     list.push(&closure); 
    } 
} 

Lưu ý rằng closure được định nghĩa trướclist là. Trong Rust, giá trị được giảm theo thứ tự từ vựng ngược ở cuối phạm vi của chúng, vì vậy bất kỳ biến nào được xác định saulist nhất thiết sẽ bị xóa trước đó, dẫn đến list chứa con trỏ không hợp lệ.

Nếu bạn muốn đẩy nhiều lần đóng, bạn sẽ cần một biến riêng biệt cho mỗi lần đóng.

Để ngăn chặn khả năng "vấn đề thực tế của tôi không phải đơn giản" phụ lục (: P): f bạn cần trả lại list hoặc theo cách nào đó, hãy vượt qua một cuộc gọi chức năng duy nhất, lưu ý rằng có là không có cách nào để mở rộng một khoản vay. Trong trường hợp đó, những gì bạn cần làm là thay đổi list thành véc tơ của thuộc sở hữu, đóng hộp đóng hộp (tức làVec<Box<Fn() -> i32>>).

Các vấn đề liên quan