2015-01-12 18 views
5

Tôi gặp sự cố khi hiểu mẫu ref trong Rust. Tôi đề cập đến https://rustbyexample.com/scope/borrow/ref.htmlVí dụ: Mẫu ref

Đây là mã tôi không hiểu:

let point = Point { x: 0, y: 0 }; 

let _copy_of_x = { 
    // `ref_to_x` is a reference to the `x` field of `point` 
    let Point { x: ref ref_to_x, y: _ } = point; 

    // Return a copy of the `x` field of `point` 
    *ref_to_x 
}; 

tôi nhận được rằng let biểu hiện cuối cùng là một số loại phù hợp với mô hình (?). Vì vậy, đó là sự hiểu biết của tôi ref ref_to_x phải bằng 0, giá trị x của số point gốc.

Nhưng tôi không hiểu những gì ref thực sự làm. Khi tôi thêm một số mã như thế này:

println!("x: {}", point.x); 
println!("ref_to_x: {}", ref_to_x); 
println!("*ref_to_x: {}", *ref_to_x); 

Tôi luôn luôn có được 0, do đó dường như không phải là một sự khác biệt. Bằng cách nào đó tôi mong đợi một địa chỉ bộ nhớ cho ref_to_x trong khi *ref_to_x có thể là giá trị đăng ký lại.

Tôi có thể thay thế cả hai ref ref_to_x*ref_to_x bằng myx và mã vẫn hoạt động. Có gì khác biệt? ref làm gì chính xác?

chỉnh sửa: sau khi đọc câu trả lời của dbaupps và thực hiện một số bổ sung với ref_to_x*ref_to_x mọi thứ trở nên rõ ràng hơn một chút; bạn không thể thêm số nguyên vào ref_to_x vì đó là số tham chiếu. Tôi đoán tôi đã nhầm lẫn vì không có dấu hiệu của một tài liệu tham khảo khi bạn in một.

Trả lời

10

ref tạo ra một con trỏ vào mảnh bộ nhớ đang được khớp lệnh trên, trong trường hợp này, ref_to_x trỏ trực tiếp vào bộ nhớ lưu trữ point.x, nó cũng giống như viết let ref_to_x = &point.x trong trường hợp này.

Mẫu là cực kỳ quan trọng, vì nó cho phép người dùng tiếp cận sâu bên trong cấu trúc dữ liệu phức tạp mà không làm xáo trộn phân cấp quyền sở hữu. Ví dụ, nếu một người có val: &Option<String>, viết

match *val { 
    Some(s) => println!("the string is {}", s), 
    None => println!("no string" 
} 

là không hợp pháp, nó mang lại cho một lỗi như:

<anon>:3:11: 3:15 error: cannot move out of borrowed content 
<anon>:3  match *val { 
        ^~~~ 
<anon>:4:14: 4:15 note: attempting to move value to here 
<anon>:4   Some(s) => {} 
        ^
<anon>:4:14: 4:15 help: to prevent the move, use `ref s` or `ref mut s` to capture value by reference 
<anon>:4   Some(s) => {} 
        ^

Nó không phải là quy phạm pháp luật để có quyền sở hữu (move) ra khỏi một giá trị vay, bởi vì điều đó có thể làm hỏng thứ mà từ đó giá trị được mượn (vi phạm các bất biến của nó, làm cho dữ liệu biến mất bất ngờ, vv).

Vì vậy, thay vào đó, bạn có thể sử dụng tham chiếu đến điểm chỉ trong bộ nhớ với tham chiếu vay &.


Có một sự tinh tế nhẹ ở đây vì (a) point không mượn, vì vậy nó là OK để di chuyển ra khỏi point (trong đó tiêu thụ quyền sở hữu của point quá, có nghĩa là nó không thể được sử dụng sau này trừ khi reinitialised) và (b) loại intCopy, do đó không di chuyển quyền sở hữu khi được sử dụng theo giá trị. Đây là lý do tại sao sử dụng myx thay vì hoạt động tốt. Nếu loại x là, ví dụ: String (không phải là Copy) và point đã được mượn, thì cần ref.

11

Tham chiếu được tạo với ref giống hệt như tham chiếu được chụp với &.

Sự khác biệt là nơi chúng được phép trong cú pháp. ref ở phía bên trái của nhiệm vụ giống như thêm & ở bên phải.

Các biểu thức này là tương đương:

let ref x1 = y; 
let x2 = &y; 

dư thừa này tồn tại vì trong mô hình kết hợp & được sử dụng để yêu cầu một tài liệu tham khảo đã tồn tại, chứ không phải là để làm cho một hình mới:

let foo = 1; 
match foo { 
    ref x => { 
     /* x == &1 */ 
     match x { 
      &y => /* y == 1 */ 
     } 
    }, 
} 

(discussion)

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