Rust - Con trỏ thông minh
Rust phân bổ mọi thứ trên ngăn xếp theo mặc định. Bạn có thể lưu trữ mọi thứ trên heap bằng cách gói chúng trong các con trỏ thông minh như Box . Các loại như Vec và String giúp phân bổ một cách ngầm định đống. Con trỏ thông minh triển khai các đặc điểm được liệt kê trong bảng dưới đây. Những đặc điểm này của con trỏ thông minh phân biệt chúng với một cấu trúc thông thường -
Sr.No | Tên đặc điểm | Gói & Mô tả |
---|---|---|
1 | Deref | std::ops::Deref Được sử dụng cho các hoạt động hội nghị bất biến, như * v. |
2 | Rơi vãi | std::ops::Drop Được sử dụng để chạy một số mã khi một giá trị nằm ngoài phạm vi. Điều này đôi khi được gọi là trình hủy |
Trong chương này, chúng ta sẽ tìm hiểu về Boxcon trỏ thông minh. Chúng ta cũng sẽ học cách tạo một con trỏ thông minh tùy chỉnh như Box.
Cái hộp
Con trỏ thông minh Box còn được gọi là hộp cho phép bạn lưu trữ dữ liệu trên heap hơn là ngăn xếp. Ngăn xếp chứa con trỏ tới dữ liệu đống. Hộp không có chi phí hoạt động, ngoài việc lưu trữ dữ liệu của chúng trên heap.
Hãy để chúng tôi xem cách sử dụng một hộp để lưu trữ giá trị i32 trên heap.
fn main() {
let var_i32 = 5;
//stack
let b = Box::new(var_i32);
//heap
println!("b = {}", b);
}
Đầu ra
b = 5
Để truy cập một giá trị được trỏ bởi một biến, hãy sử dụng hội nghị truyền thống. Dấu * được sử dụng như một toán tử hội nghị. Hãy để chúng tôi xem cách sử dụng dereference với Box.
fn main() {
let x = 5;
//value type variable
let y = Box::new(x);
//y points to a new value 5 in the heap
println!("{}",5==x);
println!("{}",5==*y);
//dereferencing y
}
Biến x là một kiểu giá trị với giá trị 5. Vì vậy, biểu thức 5 == x sẽ trả về true. Biến y trỏ đến đống. Để truy cập giá trị trong heap, chúng ta cần tham khảo bằng cách sử dụng * y. * y trả về giá trị 5. Vì vậy, biểu thức 5 == * y trả về true.
Đầu ra
true
true
Hình minh họa - Đặc điểm Deref
Đặc điểm Deref, được cung cấp bởi thư viện tiêu chuẩn, yêu cầu chúng ta triển khai một phương thức có tên là deref , phương thức này tự vay và trả về một tham chiếu đến dữ liệu bên trong. Ví dụ sau tạo một cấu trúc MyBox , là một kiểu chung. Nó thực hiện đặc điểm Deref . Đặc điểm này giúp chúng ta truy cập các giá trị heap được bao bọc bởi y bằng cách sử dụng * y .
use std::ops::Deref;
struct MyBox<T>(T);
impl<T> MyBox<T> {
// Generic structure with static method new
fn new(x:T)-> MyBox<T> {
MyBox(x)
}
}
impl<T> Deref for MyBox<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0 //returns data
}
}
fn main() {
let x = 5;
let y = MyBox::new(x);
// calling static method
println!("5==x is {}",5==x);
println!("5==*y is {}",5==*y);
// dereferencing y
println!("x==*y is {}",x==*y);
//dereferencing y
}
Đầu ra
5==x is true
5==*y is true
x==*y is true
Hình minh họa - Drop Trait
Đặc điểm Drop chứa phương thức drop () . Phương thức này được gọi khi một cấu trúc đã triển khai đặc điểm này vượt ra ngoài phạm vi. Trong một số ngôn ngữ, lập trình viên phải gọi mã để giải phóng bộ nhớ hoặc tài nguyên mỗi khi họ sử dụng xong một phiên bản của con trỏ thông minh. Trong Rust, bạn có thể tự động phân bổ bộ nhớ bằng cách sử dụng đặc điểm Drop.
use std::ops::Deref;
struct MyBox<T>(T);
impl<T> MyBox<T> {
fn new(x:T)->MyBox<T>{
MyBox(x)
}
}
impl<T> Deref for MyBox<T> {
type Target = T;
fn deref(&self) -< &T {
&self.0
}
}
impl<T> Drop for MyBox<T>{
fn drop(&mut self){
println!("dropping MyBox object from memory ");
}
}
fn main() {
let x = 50;
MyBox::new(x);
MyBox::new("Hello");
}
Trong ví dụ trên, phương thức drop sẽ được gọi hai lần khi chúng ta đang tạo hai đối tượng trong heap.
dropping MyBox object from memory
dropping MyBox object from memory