Move Semantics
Versi Bahasa Indonesia. Baca dalam Bahasa Inggris
- Setiap nilai di Rust memiliki seorang pemilik (owner).
- Hanya boleh ada satu owner pada satu waktu.
- Ketika owner keluar dari scope, nilai tersebut akan di-drop.
- Ketika menetapkan nilai ke variabel lain atau mengirimkannya ke fungsi, kepemilikan (ownership) ditransfer (dipindahkan/moved).
- Borrowing memungkinkan kamu mengakses nilai tanpa mentransfer kepemilikan, menggunakan references (
&). - Kamu hanya dapat memiliki satu mutable reference atau sejumlah immutable reference pada satu waktu.
- Referensi:
move_semantics1.rs
// TODO: Fix the compiler error in this function.
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
let mut vec = vec;
vec.push(88);
vec
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn move_semantics1() {
let vec0 = vec![22, 44, 66];
let vec1 = fill_vec(vec0);
assert_eq!(vec1, vec![22, 44, 66, 88]);
}
}- Di latihan ini fungsi
fill_vecmencoba mengubah variabelvec. - Tapi ia mendapat compile error karena
vectidak mutable. - Saat mengirimkan
vec0ke dalam fungsifill_vec, ia juga mentransfer atau memindahkan kepemilikan dari fungsimainke fungsifill_vec. - Jadi
fill_vecsebagai owner dapat melakukan apa saja dengannya termasuk mengubah mutability. - Maka kita dapat dengan mudah menambahkan mutable di sini
let mut vec = vec;untuk memperbaiki kode. - Dan itu membuat
vecmenjadi mutable dan kita dapat melakukan push nilai ke dalamnya.
move_semantics2.rs
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
let mut vec = vec;
vec.push(88);
vec
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
// TODO: Make both vectors `vec0` and `vec1` accessible at the same time to
// fix the compiler error in the test.
#[test]
fn move_semantics2() {
let vec0 = vec![22, 44, 66];
let vec1 = fill_vec(vec0.clone()); // pass cloned vec0
assert_eq!(vec0, [22, 44, 66]);
assert_eq!(vec1, [22, 44, 66, 88]);
}
}-
Di latihan ini tugasnya adalah membuat
vec0danvec1dapat diakses pada waktu yang bersamaan. -
Jika kita mengirimkan
vec0ke fungsifill_vecmaka ia akan mentransfer atau memindahkan kepemilikan. -
Itu membuat variabel
vec0menjadi tidak valid dan kita mendapatkan error:borrow of moved value: `vec0` -
Jadi alih-alih mengirimkan
vec0, kita mengirimkan clone darivec0. -
Itu membuat
vec0danvec1tetap valid.
move_semantics3.rs
// TODO: Fix the compiler error in the function without adding any new line.
fn fill_vec(mut vec: Vec<i32>) -> Vec<i32> {
// ^^^ add mut
vec.push(88);
vec
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn move_semantics3() {
let vec0 = vec![22, 44, 66];
let vec1 = fill_vec(vec0);
assert_eq!(vec1, [22, 44, 66, 88]);
}
}- Latihan ini mirip dengan
move_semantics1.rs. - Tapi alih-alih mengubah mutability dengan mendeklarasikan ulang variabel dengan
mut, kita melakukannya di dalam parameter fungsi.
move_semantics4.rs
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
// TODO: Fix the compiler errors only by reordering the lines in the test.
// Don't add, change or remove any line.
#[test]
fn move_semantics4() {
let mut x = Vec::new();
let y = &mut x;
y.push(42); // move this line above z
let z = &mut x;
z.push(13);
assert_eq!(x, [42, 13]);
}
}-
Kamu hanya dapat memiliki satu mutable reference atau sejumlah immutable reference pada satu waktu.
-
Jadi kode asli memiliki compile error karena
xmemiliki lebih dari satu mutable reference.error[E0499]: cannot borrow `x` as mutable more than once at a time --> exercises/06_move_semantics/move_semantics4.rs:13:17 | 12 | let y = &mut x; | ------ first mutable borrow occurs here 13 | let z = &mut x; | ^^^^^^ second mutable borrow occurs here 14 | y.push(42); | - first borrow later used here -
Dengan memindahkan
y.push(42);ke ataslet z = &mut x;kita dapat memperbaikinya. -
Karena
ysudah selesai dengan push-nya, makaxbebas dan dapat dipinjam olehzdi langkah selanjutnya.
move_semantics5.rs
#![allow(clippy::ptr_arg)]
// TODO: Fix the compiler errors without changing anything except adding or
// removing references (the character `&`).
// Shouldn't take ownership
// add & to borrow instead
fn get_char(data: &String) -> char {
data.chars().last().unwrap()
}
// Should take ownership
fn string_uppercase(mut data: String) {
data = data.to_uppercase();
println!("{data}");
}
fn main() {
let data = "Rust is great!".to_string();
get_char(&data);
string_uppercase(data);
}- Jika kita lihat komentarnya, fungsi
get_charseharusnya tidak mengambil kepemilikan tetapi kode asli melakukannya. - Jadi kita hanya perlu menambahkan reference
&pada parameterdata: &Stringdan mengirimkan&datasaat memanggilget_char. - Itu membuatnya meminjam (borrow) alih-alih memindahkan (move).
- Untuk
string_uppercasehapus reference dari parameter data karena kita ingin memindahkan kepemilikan ke fungsi tersebut dan hapus juga reference saat memanggilnya.
Last updated on