Rust Notes #1: Move

Author

Thâm / December 28, 2024

3 min read––– lượt xem

Giới thiệu

Trong Rust, việc hiểu về cách biến và dữ liệu tương tác thông qua Move là một khái niệm cơ bản và quan trọng. Move là một cơ chế độc đáo của Rust, giúp đảm bảo an toàn bộ nhớ và tránh các lỗi phổ biến trong lập trình hệ thống.

Nội dung

Move (Di chuyển) trong Rust

Move là quá trình chuyển quyền sở hữu (ownership) của một giá trị từ biến này sang biến khác. Đặc điểm quan trọng của Move là sau khi chuyển, biến ban đầu không còn sử dụng được nữa.

Tại sao cần Move?

Move giúp Rust đảm bảo an toàn bộ nhớ thông qua các cơ chế:

  • Ngăn chặn việc hai biến cùng giải phóng một vùng nhớ
  • Tránh lỗi double free
  • Đảm bảo mỗi vùng nhớ chỉ có một chủ sở hữu tại một thời điểm

Các kiểu dữ liệu và Move

Stack types

Các kiểu dữ liệu được lưu trên stack có đặc điểm:

  • Kích thước cố định (integers, floats, bool, char)
  • Được sao chép (copy) thay vì move
  • Cả biến gốc và biến mới đều sử dụng được
let x = 5;
let y = x; // x được copy sang y 
println!("x = {}, y = {}", x, y); // Cả hai đều dùng được
Heap types

Các kiểu dữ liệu được lưu trên heap:

  • Bao gồm String, Vec, Box, và các kiểu phức tạp khác
  • Thực hiện move thay vì copy
  • Biến gốc không còn sử dụng được sau khi move
let s1 = String::from("hello");
let s2 = s1;    // s1 move vào s2
// s1 không còn dùng được nữa
Move trong Functions

Di chuyển ownership vào functions

fn main() {
    let s = String::from("hello");
    takes_ownership(s);    // s move vào hàm
    // s không còn dùng được ở đây

    let x = 5;
    makes_copy(x);        // x được copy
    println!("{}", x);    // x vẫn dùng được
}

fn takes_ownership(str: String) {
    println!("{}", str);
}    // str bị drop ở đây

Một số cách để tránh Move

  1. Clone Tạo một bản sao sâu của dữ liệu:
let s1 = String::from("hello");
let s2 = s1.clone();    // Tạo bản sao thay vì move
println!("s1 = {}, s2 = {}", s1, s2);
  1. References Sử dụng tham chiếu thay vì lấy ownership:
fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1);    // Mượn tham chiếu
    println!("Length of '{}' is {}", s1, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

Kết luận

Move trong Rust là một khái niệm quan trọng trong hệ thống ownership của ngôn ngữ này. Nó giúp đảm bảo an toàn bộ nhớ tại thời điểm biên dịch mà không cần garbage collector. Hiểu rõ về Move sẽ giúp lập trình viên viết code Rust an toàn và hiệu quả hơn.

Việc nắm vững cách hoạt động của Move cũng như biết cách sử dụng các giải pháp thay thế như Clone và References là kỹ năng thiết yếu khi lập trình với Rust. Điều này không chỉ giúp tránh được các lỗi phổ biến mà còn tận dụng được sức mạnh của hệ thống ownership độc đáo của Rust.

Đăng ký nhận thông báo qua email khi có bài viết mới

0 người đăng ký