After reading Rust book chapter 4

rust

소유권 (Ownership)

배경


규칙


사례: String 타입

let s = "hello";
let s2 = String::from("hello");


String 타입에서의 메모리 할당

해당 메모리는 반드시 런타임에 운영체제에 요청해야 하고, String 타입의 사용이 완료되면 이 메모리를 운영체제에 다시 돌려줄 방법이 필요하다.


(1) 변수-데이터가 상호작용하는 방식: 이동(move)

let x = 5;
let y = x;

println!(println!("{}", x);

let s1 = String::from("hello");
let s2 = s1;

// value used here after move
println!("{}", s1);


(2) 변수-데이터가 상호작용하는 방식: 복제(clone)

let s1 = String::from("hello");
let s2 = s1.clone();

println!("s1 = {}, s2 = {}", s1, s2);


(3) 스택 전용 데이터: 복사(copy)

let x = 5;
let y = x;

println!("x = {}, y = {}", x, y);


Ownership and Functions

fn main() {
    let s = String::from("hello");

    takes_ownership(s);

    let x = 5;

    makes_copy(x);
}

fn takes_ownership(some_string: String) {
    println!("{}", some_string);
}
// Here, some_string goes out of scope and `drop` is called. The backing
// memory is freed.

fn makes_copy(some_integer: i32) {
    println!("{}", some_integer);
}
// Here, some_integer goes out of scope. Nothing special happens.


Return Values and Scope

fn main() {
    let s1 = gives_ownership();
    let s2 = String::from("hello");
    let s3 = takes_and_gives_back(s2);
}

fn gives_ownership() -> String {
    let some_string = String::from("yours");

    some_string
}

fn takes_and_gives_back(a_string: String) -> String {
    a_string
}



References and Borrowing

fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1);

    println!("The length of '{}' is {}.", s1, len);
}

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


가변 참조 (Mutable References)

fn main() {
    let mut s = String::from("hello");

    change(&mut s);
}

fn change(some_string: &mut String) {
    some_string.push_str(", world");
}
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s;

println!("{}, {}", r1, r2);


let mut s = String::from("hello");

let r1 = &s; // no problem
let r2 = &s; // no problem
let r3 = &mut s; // BIG PROBLEM

println!("{}, {}, and {}", r1, r2, r3);
let mut s = String::from("hello");

let r1 = &s; // no problem
let r2 = &s; // no problem
println!("{} and {}", r1, r2);
// variables r1 and r2 will not be used after this point

let r3 = &mut s; // no problem
println!("{}", r3);


fn main() {
    let reference_to_nothing = dangle();
}

fn dangle() -> &String {
    let s = String::from("hello");

    &s
}



Slice Type

(1) 문자열 슬라이스

fn main() {
    let mut s = String::from("hello world");
    let word = first_word(&s);

    s.clear();
}

fn first_word_length(s: &String) -> usize {...}
fn second_word_length(s: &String) -> (usize, usize) {...}


let s = String::from("hello world");

let hello = &s[0..5];
let world = &s[6..11];
let s = String::from("hello");
let len = s.len();

// (1)
let slice = &s[0..2];
let slice = &s[..2];

// (2)
let slice = &s[3..len];
let slice = &s[3..];

// (3)
let slice = &s[0..len];
let slice = &s[..];


fn main() {
    let mut s = String::from("hello world");
    let word = first_word(&s);

    s.clear(); // error!

    println!("the first word is: {}", word);
}

fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }

    &s[..]
}


let s = "Hello, world!";


// AS-IS
fn first_word(s: &String) -> &str {}

// TO-BE
fn first_word(s: &str) -> &str {}


(2) 그외 타입 슬라이스

let a = [1, 2, 3, 4, 5];
let slice = &a[1..3];