2015-06-09 25 views
6

Trong Rust Book có một ví dụ về gọi filter() trên một iterator:Sự khác biệt giữa bộ lọc (| x |) và bộ lọc (| & x |) là gì?

for i in (1..100).filter(|&x| x % 2 == 0) { 
    println!("{}", i); 
} 

Có một lời giải thích dưới đây nhưng tôi đang gặp rắc rối hiểu nó:

This will print all of the even numbers between one and a hundred. (Note that because filter doesn't consume the elements that are being iterated over, it is passed a reference to each element, and thus the filter predicate uses the &x pattern to extract the integer itself.)

này, tuy nhiên không hoạt động :

for i in (1..100).filter(|&x| *x % 2 == 0) { 
    println!("i={}", i); 
} 

Tại sao đối số đóng tài liệu tham chiếu |&x|, inst ead của |x|? Và sự khác nhau giữa việc sử dụng |&x||x| là gì?

Tôi hiểu rằng việc sử dụng một tài liệu tham khảo |&x| là hiệu quả hơn, nhưng tôi bối rối bởi thực tế là tôi không phải dereference con trỏ x bằng cách sử dụng *x.

Trả lời

8

Khi sử dụng như một mô hình phù hợp (và đóng cửa và chức năng đối số là cũng phù hợp với mô hình), các &liên kết đến một tài liệu tham khảo, làm cho biến các dereferenced giá trị.

fn main() { 
    let an_int: u8 = 42; 
    // Note that the `&` is on the right side of the `:` 
    let ref_to_int: &u8 = &an_int; 
    // Note that the `&` is on the left side of the `:` 
    let &another_int = ref_to_int; 
    let() = another_int; 
} 

Có lỗi:

error: mismatched types: 
expected `u8`, 
    found `()` 

Nếu bạn nhìn vào thông báo lỗi của bạn đối với trường hợp của bạn, nó chỉ ra rằng bạn có thể không dereference nó, bởi vì nó không phải là một tài liệu tham khảo:

error: type `_` cannot be dereferenced 

I didn't have to dereference the x pointer by using *x.

đó là bởi vì bạn ngầm dereferenced nó trong khớp mẫu.

I understand that using a reference |&x| is more efficient

Nếu điều này đúng, thì sẽ không có lý do gì để sử dụng bất cứ điều gì ngoài tham chiếu! Cụ thể, tài liệu tham khảo yêu cầu thêm hướng dẫn để có được các dữ liệu thực tế. Có một số điểm cắt có thể đo lường khi chuyển các mục theo giá trị hiệu quả hơn so với truyền tham chiếu đến chúng.

If so, why does using |x| not throw an error? From my experience with C, I would expect to receive a pointer here.

Và bạn thực hiện, dưới dạng tham chiếu . x là tham chiếu đến (trong ví dụ này) là i32. Tuy nhiên, các nhà điều hành % được cung cấp bởi các đặc điểm Rem, được thực hiện cho tất cả các cặp tài liệu tham khảo/giá trị:

impl Rem<i32> for i32 
impl<'a> Rem<i32> for &'a i32 
impl<'a> Rem<&'a i32> for i32 
impl<'a, 'b> Rem<&'a i32> for &'b i32 

này cho phép bạn không cần phải rõ ràng dereference nó.

Or does Rust implicitly allocate a copy of value of the original x on the stack here?

Nó nhấn mạnh không làm điều đó. Trong thực tế, sẽ không an toàn để làm điều đó, trừ khi các mục lặp lại được triển khai Copy (hoặc có khả năng là Clone, trong trường hợp này nó cũng có thể tốn kém). Đây là lý do tại sao tham chiếu được sử dụng làm đối số đóng.

+0

Vì vậy, 'let & x = my_pointer' thực sự là một thay thế cho' let x = * my_pointer', và nó cũng hoạt động trong khai báo tham số hàm? Nếu vậy, tại sao sử dụng '| x |' không ném một lỗi? Từ kinh nghiệm của tôi với C, mong đợi sẽ nhận được một con trỏ ở đây. Hoặc không gỉ ngầm phân bổ một bản sao của giá trị của bản gốc 'x' trên ngăn xếp ở đây? – jeremija

+0

Ohhh, tôi đã có rất nhiều điều để học :) Cảm ơn bạn - nó rõ ràng hơn nhiều với tôi bây giờ! – jeremija

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