informasi kontak saya
Surat[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Halo semuanya
Hari ini saya menyelesaikan Kamp Pelatihan Pengembangan OS Mengemudi Otonom 2024 - Kamp Dasar Tahap Keempat - Tutorial
Hari ke-2 Berlatih bahasa Rust dengan Semantik Rustling-Move
https://doc.rust-lang.org/stable/book/ch04-00-memahami-kepemilikan.html
Ketika saya mengirimkan kode, saya mendapat pesan bahwa saya tidak memiliki izin. Bagaimana cara saya keluar?
tindakan
Konfigurasi lingkungan pengembangan referensi
https://rcore-os.cn/buku-tutorial-arceos/ch01-02.html
topik saya
https://github.com/cicvedu/rustlings-semester-4-poin-perhatian
Buat kunci ssh untuk mengkloning kode github melalui ssh. Di lingkungan Linux, gunakan perintah ssh-keygen -t rsa -b 4096 -C "kotak surat Anda" untuk membuat kunci ssh. Cukup tekan Enter untuk semua opsi berikut. Kemudian gunakan cat ~/.ssh/id_rsa.pub
Rust memiliki beberapa tipe dasar yang langsung diimplementasikan ke dalam kompiler. Di bagian ini, kita akan membahas beberapa tipe yang paling penting.
Jenis Irisan Irisan memungkinkan Anda merujuk pada urutan elemen yang bersebelahan dalam satu koleksi, bukan keseluruhan koleksi.
Potongan adalah sejenis referensi, jadi tidak memiliki kepemilikan.
Di Rust, irisan adalah tampilan yang mereferensikan rangkaian elemen yang berdekatan dari array atau irisan lainnya. Untuk membuat irisan, Anda perlu menentukan posisi awal dan akhir irisan (tidak termasuk indeks posisi akhir).dalam susunana
masuk jika Anda ingin mendapatkannya[2, 3, 4]
Untuk potongan ini, Anda harus memulai pada indeks 1 dan mengakhiri pada indeks 4 (tidak termasuk indeks 4).
Berikut cara memperbaiki kode pengujian Anda:
#[test]
fn slice_out_of_array() {
let a = [1, 2, 3, 4, 5];
// 从索引 1 开始,到索引 4 结束的切片
let nice_slice = &a[1..4];
assert_eq!([2, 3, 4], nice_slice);
}
Dalam contoh ini,&a[1..4]
Membuat array daria
Irisan dimulai pada indeks 1 dan berakhir pada indeks 3, karena sintaks pemotongan Rust adalah interval kiri-tertutup dan kanan-terbuka (termasuk awal, tetapi bukan akhir).Jadinice_slice
Ini berisi arraya
tengah[2, 3, 4]
。
Masukkan jam tangan gemerisik pada baris perintah untuk memulai percobaan loop dalam mengedit kode
Memahami Kepemilikan
Kepemilikan adalah fitur Rust yang paling unik dan memiliki implikasi mendalam bagi bahasa lainnya.
Hal ini memungkinkan Rust untuk membuat jaminan keamanan memori tanpa memerlukan pengumpulan sampah
Apa itu Kepemilikan?
Aturan Kepemilikan Pertama, mari kita lihat aturan kepemilikan. Ingatlah aturan-aturan ini saat kita membahas contoh-contoh yang mengilustrasikannya:
Contoh kodenya sendiri sudah benar dan menunjukkan konsep kepemilikan dan penyalinan di Rust. Namun, jika Anda ingin memastikan kode Anda dikompilasi dan dijalankan, dan Anda ingin mengatasi beberapa kemungkinan perbaikan atau koreksi, berikut beberapa saran:
memastikan takes_ownership
Danmakes_copy
berfungsi dimain
fungsi yang ditentukan sebelumnya, karena fungsi di Rust perlu dideklarasikan terlebih dahulu baru kemudian digunakan.
menambahkan catatan, jelaskan mengapa s
adatakes_ownership
tidak dapat digunakan setelah dipanggil, danx
adamakes_copy
Itu masih dapat digunakan setelah dipanggil.
Tambahkan main
tipe pengembalian fungsi, meskipun hal ini tidak diperlukan dalam program sederhana, ini merupakan praktik pemrograman yang baik.
Menggunakan alat pemformatan Rust,Misalnya rustfmt
, untuk menjaga kode tetap bersih.
Berikut adalah kode yang dimodifikasi berdasarkan saran di atas:
fn takes_ownership(some_string: String) { // 函数定义在 main 之前
println!("{}", some_string);
} // some_string 的作用域结束,调用 Drop
fn makes_copy(some_integer: i32) { // 函数定义在 main 之前
println!("{}", some_integer);
} // some_integer 的作用域结束,没有调用 Drop,因为 i32 是 Copy 类型
fn main() -> () { // 明确 main 函数的返回类型为 ()
let s = String::from("hello"); // s 拥有 "hello" 的所有权
takes_ownership(s); // s 的值移动到 takes_ownership 函数
// 下面的代码尝试使用 s 将会导致编译错误,因为 s 的值已经移动
// let len = s.len(); // 错误:s 已移动
let x = 5; // x 包含值 5
makes_copy(x); // x 的值被复制到 makes_copy 函数
// x 仍然有效,因为 i32 是 Copy 类型
// x 仍然可以使用
println!("x is {}", x);
}
Dalam versi revisi ini kami telah menambahkan main
tipe pengembalian fungsi()
,ini berarti main
Fungsi ini tidak mengembalikan nilai.Juga, komentar ditambahkan untuk menjelaskan alasannyas
adatakes_ownership
tidak dapat digunakan setelah dipanggil, danx
adamakes_copy
Masih berlaku setelah menelepon.Selain itu, kami menunjukkan upaya untuktakes_ownership
Gunakan setelah menelepons
Contoh yang akan menyebabkan kesalahan kompilasi, danx
adamakes_copy
Contoh yang masih bisa digunakan setelah menelepon.
Vektor adalah salah satu struktur data Rust yang paling banyak digunakan.
Dalam bahasa pemrograman lain, mereka akan disebut Array saja, tetapi karena Rust beroperasi pada level yang sedikit lebih rendah, array dalam Rust disimpan di tumpukan (artinya array tidak dapat bertambah atau berkurang, dan ukurannya perlu diketahui pada waktu kompilasi), dan Vektor disimpan di dalam tumpukan (yang tidak menerapkan batasan ini).
Vektor merupakan topik yang dibahas di bab selanjutnya dalam buku ini, tetapi kami rasa cukup bermanfaat untuk dibahas lebih awal. Kami akan membahas struktur data bermanfaat lainnya, yaitu peta hash, nanti.
vec_map
Fungsinya untuk menerima aVec<i32>
ketik (yaitu vektor yang berisi bilangan bulat 32-bit), lalu kembalikan yang baruVec<i32>
, setiap elemen dalam vektor baru ini berukuran dua kali ukuran elemen yang bersesuaian dalam vektor asli.
Secara khusus,vec_map
dalam fungsimap
Dancollect
Metode kerjanya seperti ini:
**v.iter()
**: Metode ini membuat iterator yang melintasi v
setiap elemen vektor.iter
Iterator yang dikembalikan oleh metode ini memberikan referensi yang tidak dapat diubah ke elemen dalam vektor.
**.map(|element| { element * 2 })
**:map
Metode menerima penutupan (fungsi anonim), dalam hal ini penutupan menerima satu parameterelement
(referensi yang tidak dapat diubah ke elemen dalam vektor) dan kemudian mengembalikan nilai elemen ini dikalikan 2.Operasi di dalam penutupanelement * 2
Faktanya, Anda melakukan dereferensi data yang ditunjuk oleh referensi (via*
operator) dan melakukan operasi perkalian.
**.collect()
**:map
Metode ini mengembalikan iterator malas yang menerapkan operasi dalam penutupan satu per satu, namun tidak segera mengumpulkan hasilnya.collect
metode dipanggil untuk meneruskan inimap
Elemen yang telah diproses dikumpulkan menjadi yang baruVec<i32>
dalam vektor.
menggunakan map
Dancollect
Manfaatnya adalah mereka memungkinkan Anda melakukan operasi pada setiap elemen dalam koleksi dengan cara deklaratif dan mengumpulkan hasilnya ke dalam koleksi baru tanpa perlu menulis loop eksplisit. Dengan cara ini kodenya lebih ringkas dan lebih konsisten dengan gaya Rust.
Berikut adalah cara menggunakannya vec_map
Contoh fungsi:
fn main() {
let original_vec = vec![1, 2, 3, 4];
let doubled_vec = vec_map(&original_vec);
println!("{:?}", doubled_vec); // 这将打印:[2, 4, 6, 8]
}
Dalam contoh ini,vec_map
mengambil alihoriginal_vec
referensi, membuat vektor barudoubled_vec
, yang berisi dua kali nilai setiap elemen vektor asli dan mencetaknya.
Latihan ini diadaptasi dari pnkfelix'S Tutorial Karat -- Terima kasih Felix!!!
Untuk bagian ini, tautan buku sangatlah penting.
Ada aturan untuk referensi yang dapat diubah di Rust: pada waktu tertentu, Anda dapat memiliki sejumlah referensi yang tidak dapat diubah, atau paling banyak satu referensi yang dapat diubah. Aturan ini memastikan keamanan memori dan mencegah data race.
Pada kode yang diberikan, ada masalah:main
Fungsi tersebut mencoba membuat dua referensi yang bisa berubahy
Danz
, keduanya menunjuk ke variabel yang sama x
. Hal ini tidak diperbolehkan karena aturan peminjaman Rust tidak mengizinkan beberapa referensi yang bisa diubah ke variabel yang sama dalam cakupan yang sama. Itu sebabnya kodenya tidak dapat dikompilasi.
Untuk memperbaiki masalah ini, Anda perlu memastikan bahwa hanya ada satu referensi yang dapat diubah pada waktu tertentu. Ini kode tetapnya:
fn main() {
let mut x = 100;
{
let y = &mut x;
*y += 100; // 此时 x 的值变为 200
} // 'y' 的作用域结束,可变引用被销毁
{
let z = &mut x; // 可以创建新的可变引用,因为 'y' 已经不存在了
*z += 1000; // 此时 x 的值变为 1200
} // 'z' 的作用域结束,可变引用被销毁
assert_eq!(x, 1200); // 断言 x 的值是 1200,这是正确的
}
Dalam versi tetap ini, kami memastikan bahwa hanya ada satu referensi yang dapat diubah setiap saat dengan membuat cakupan dalam.Pertama, kami membuaty
ruang lingkup, operasi dilakukan padanya, dan kemudian ruang lingkup ini berakhir,y
Tidak berlaku lagi.Setelah itu, kami membuatz
ruang lingkup, sekali lagi untukx
Lakukan operasi. Ini mengikuti aturan peminjaman Rust sehingga kode dikompilasi dan berjalan seperti yang diharapkan.
Pesan kesalahan kompilasi ini menunjukkan masalah siklus hidup dalam kode Rust.Masalahnya adalahstring_uppercase
Dalam implementasi fungsinya, ia mencoba untuk menetapkan nilai sementara ke referensi, yang tidak diperbolehkan.
Berikut baris kode yang salah:
data = &data.to_uppercase();
Di baris kode ini,data.to_uppercase()
Dibuat aString
Contoh baru daridata
dipinjam.Namun, coba tetapkan referensi ke nilai sementara inidata
adalah ilegal karena nilai sementara dimusnahkan segera pada akhir pernyataan, dandata
Membutuhkan masa pakai yang lebih lama dibandingkan nilai sementara.
Untuk memperbaiki masalah ini kita perlu memodifikasi string_uppercase
Sebuah fungsi yang menerima referensi yang bisa diubah dan memanggilnya langsung pada data yang ditunjuk oleh referensi tersebutmake_uppercase()
metode alih-alih mencoba menugaskan kembali. Ini kode tetapnya:
fn string_uppercase(data: &mut String) {
data.make_uppercase(); // 直接在 data 上调用 make_uppercase 方法
println!("{}", data);
}
Dalam versi tetap ini kami telah menghapusnya mut data: &String
tengahmut
,Karena data
Sudah menjadi referensi yang bisa berubah.Lalu kita langsungdata
panggilmake_uppercase()
, jadi tidak akan ada masalah dengan nilai sementara.make_uppercase()
Metodenya akan diubahdata
titik referensi keString
contoh tanpa membuat yang baruString
。
Juga,main
Panggilan dalam fungsi juga perlu diperbarui agar dapat memberikan referensi yang bisa diubah:
fn main() {
let mut data = "Rust is great!".to_string();
string_uppercase(&mut data); // 传递一个可变引用
println!("{}", data); // 打印修改后的字符串
}
Sekarang,string_uppercase
fungsi menerimadata
referensi yang bisa berubah, memodifikasinya secara langsung, danmain
dalam fungsidata
bisa berubah dan bisa sajastring_uppercase
diubah. Dengan cara ini kode dikompilasi dan berfungsi seperti yang diharapkan.
/**
【昵称】小王同学
【坐标】山东
【自我介绍】
1. 高级后端工程师,擅长c++并发编程。
2. 专注分布式存储,分布式数据库。
3. 时间的践行者,立志成为一名讲师。
【我的成绩】
1. 为了走出农村,2次高考
一次考研失败,
遇挫之后不知道干什么,开启被动之旅。
2. 为了找到合适工作,
深入研究c++书籍和leetcode 200题目
3. 为了提高项目能力,参与开源项目建设。
4. 为了把简单事情说清楚/要干啥
按照《只管去做》,《福格行为模型>>方法。
纸上得来终觉浅,绝知此事要躬行
做一个践行者。
【我能提供】
1. 后端程序员的简历优化+就业辅导+职业规划
2. 全栈工程师(c++,rust,go,python )项目开发
3. 一年践行12本书践行记录。
【希望一起解决什么,开启破圈之旅】
1. 交接更多朋友,抱团取暖。
寻找意义本身就更加有意义。
2. 无法做整个系统,聚焦一个模块
道可道也,非恒道也
名可名也,非恒名也。
无名 万物之始也
有名 万物之母也
别想太多,只管去做,躬身入局
链接我: # + v(github):watchpoints
#众号:后端开发成长指南
**/
Artikel ini ditulis oleh bagus sekaliPenerbitan multi-platform