2015-01-11 14 views
8

Trên bề mặt, có vẻ như cả draininto_iter cung cấp các trình lặp tương tự, cụ thể là trên các giá trị của bộ sưu tập. Tuy nhiên, họ là khác nhau:Khi nào tôi nên sử dụng `drain` vs` into_iter`?

fn main() { 
    let mut items1 = vec![0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9]; 
    let items2 = items1.clone(); 

    println!("{:?}", items1.drain().count()); 
    println!("{:?}", items2.into_iter().count()); 

    println!("{:?}", items1); 
    // println!("{:?}", items2); Moved 
} 

drain mất một &mut đến việc thu thập và bộ sưu tập có sẵn sau đó. into_iter tiêu thụ bộ sưu tập. Sử dụng thích hợp cho mỗi trình lặp là gì?

Trả lời

8

Chúng hơi dư thừa với nhau. Tuy nhiên, như bạn nói, Drain chỉ vay mượn vectơ, đặc biệt, nó có tuổi thọ được kết nối với vectơ. Nếu có nhu cầu trả lại một trình lặp, hoặc ngược lại, hãy tránh các trình vòng lặp theo cách linh hoạt nhất có thể, sử dụng into_iter là tốt hơn, vì nó không bị xích vào chủ sở hữu của số Vec có nguồn gốc. Nếu có nhu cầu sử dụng lại cấu trúc dữ liệu (ví dụ: sử dụng lại phân bổ) thì drain là cách trực tiếp nhất để thực hiện việc này.

Ngoài ra, một (hơi) quan tâm lý thuyết là Drainnhu cầu dẫn đến cấu trúc có nguồn gốc là một trường hợp giá trị của bất cứ loại đó là, đó là, hoặc là duy trì bất biến, hoặc sửa chữa chúng lên ở cuối, trong khi IntoIter có thể mangle cấu trúc nhiều như nó thích, vì nó có toàn quyền kiểm soát giá trị.

tôi nói chỉ "hơi" lý thuyết bởi vì có một nhỏ, thực ví dụ thế giới này trong std đã: HashMap lộ .drain.into_iter qua nội RawTable loại của nó, mà còn có các phương pháp đó. into_iter chỉ có thể read the hash of the value being moved directly và đó là điều đó, nhưng drain phải cẩn thận to update the hash to indicate that the cell is then empty, không chỉ đọc nó. Rõ ràng điều này là hoàn toàn nhỏ trong trường hợp này (có lẽ chỉ một hoặc hai hướng dẫn bổ sung) nhưng đối với các cấu trúc dữ liệu phức tạp hơn như cây có thể có một số lợi ích không tầm thường có được từ việc phá vỡ các bất biến của cấu trúc dữ liệu.

7

Sau khi sử dụng drain, Vec trống nhưng bộ nhớ được phân bổ trước đó cho các phần tử của nó vẫn được phân bổ. Điều này có nghĩa là bạn có thể chèn các phần tử mới vào số Vec mà không phải phân bổ dung lượng lưu trữ cho chúng cho đến khi bạn đạt đến số capacity của Vec.

Lưu ý rằng trước khi bạn có thể sử dụng lại Vec, bạn phải thả tất cả các tham chiếu đến trình lặp vòng Drain. Việc triển khai Drain của Drop sẽ xóa tất cả các thành phần chưa được xóa khỏi số Vec, vì vậy, Vec sẽ trống ngay cả khi bạn không hoàn thành việc lặp lại.

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