๋ณธ๋ฌธ์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

1-3. references borrowing

ยท 4๋ถ„ ์ฝ๊ธฐ

Day 6-8: References & Borrowing ์š”์•ฝ

๐ŸŽฏ ํ•ต์‹ฌ ๊ฐœ๋…

์™œ ํ•„์š”ํ•œ๊ฐ€?

Day 3-5์—์„œ ๋ฐœ๊ฒฌํ•œ ๋ฌธ์ œ: ํ•จ์ˆ˜์— ๊ฐ’์„ ๋„˜๊ธฐ๋ฉด ์†Œ์œ ๊ถŒ์ด ์ด๋™ โ†’ ์›๋ž˜ ๋ณ€์ˆ˜ ์‚ฌ์šฉ ๋ถˆ๊ฐ€

fn takes_ownership(s: String) { println!("{}", s); }
 
let s = String::from("hello");
takes_ownership(s);
// println!("{}", s);  // โŒ ์†Œ์œ ๊ถŒ ์ด๋™๋จ!

ํ•ด๊ฒฐ์ฑ…: ์†Œ์œ ๊ถŒ์„ ๋„˜๊ธฐ์ง€ ์•Š๊ณ  ๋นŒ๋ ค์ฃผ๊ธฐ(Borrowing)


๐Ÿ“Œ ๋‘ ์ข…๋ฅ˜์˜ ์ฐธ์กฐ

1. Immutable Reference (&T) โ€” ์ฝ๊ธฐ ์ „์šฉ

fn calculate_length(s: &String) -> usize {
    s.len()  // ์ฝ๊ธฐ๋งŒ ๊ฐ€๋Šฅ
}
 
let s = String::from("hello");
let len = calculate_length(&s);  // ๋นŒ๋ ค์คŒ
println!("{}", s);               // โœ… ์—ฌ์ „ํžˆ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

2. Mutable Reference (&mut T) โ€” ์ˆ˜์ • ๊ฐ€๋Šฅ

fn change(some_string: &mut String) {
    some_string.push_str(", world");  // ์ˆ˜์ • ๊ฐ€๋Šฅ
}
 
let mut s = String::from("hello");  // ์›๋ณธ๋„ mut์ด์–ด์•ผ ํ•จ!
change(&mut s);                      // mutable๋กœ ๋นŒ๋ ค์คŒ
println!("{}", s);                   // "hello, world"

Python๊ณผ์˜ ์ฐจ์ด

PythonRust &TRust &mut T
์ฝ๊ธฐโœ…โœ…โœ…
์ˆ˜์ •โœ…โŒโœ…

Python์€ ์ฐธ์กฐ๋ฅผ ํ†ตํ•ด ๋งˆ์Œ๋Œ€๋กœ ์ˆ˜์ • ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, Rust๋Š” ๋ช…์‹œ์ ์œผ๋กœ &mut์„ ์จ์•ผ๋งŒ ์ˆ˜์ • ๊ฐ€๋Šฅ


๐Ÿ“Œ Borrowing ํ•ต์‹ฌ ๊ทœ์น™ (2๊ฐ€์ง€)

๊ทœ์น™ 1: &mut T๋Š” ๋™์‹œ์— 1๊ฐœ๋งŒ

let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s;  // โŒ ๋‘ ๋ฒˆ์งธ mutable ์ฐธ์กฐ ๋ถˆ๊ฐ€!
println!("{}, {}", r1, r2);

์ด์œ : ๋‘ ๊ณณ์—์„œ ๋™์‹œ์— ์ˆ˜์ •ํ•˜๋ฉด ๋ฐ์ดํ„ฐ ์ถฉ๋Œ

๊ทœ์น™ 2: &T์™€ &mut T ๋™์‹œ ์‚ฌ์šฉ ๋ถˆ๊ฐ€

let mut s = String::from("hello");
let r1 = &s;       // ๐Ÿ“– ์ฝ๊ธฐ
let r2 = &s;       // ๐Ÿ“– ์ฝ๊ธฐ
let r3 = &mut s;   // โŒ ์ฝ๋Š” ์ค‘์— ์ˆ˜์ • ๋ถˆ๊ฐ€!
println!("{}, {}, {}", r1, r2, r3);

์ด์œ : ์ฝ๋Š” ์ค‘์— ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ์œ„ํ—˜

์˜ˆ์™ธ: &T ์—ฌ๋Ÿฌ ๊ฐœ๋Š” OK

let s = String::from("hello");
let r1 = &s;  // โœ…
let r2 = &s;  // โœ…
let r3 = &s;  // โœ… ์ฝ๊ธฐ๋ผ๋ฆฌ๋Š” ์•ˆ์ „!

๋„์„œ๊ด€ ๋น„์œ 

  • &T (์ฝ๊ธฐ) = ์—ฌ๋Ÿฌ ๋ช…์ด ๋™์‹œ์— ์ฑ… ์ฝ๊ธฐ โ†’ OK
  • &mut T (์ˆ˜์ •) = ํ•œ ๋ช…๋งŒ ํŽœ์œผ๋กœ ์ˆ˜์ • ๊ฐ€๋Šฅ โ†’ ๋™์‹œ์— ๋‘ ๋ช… ๋ถˆ๊ฐ€
  • &T + &mut T = ์ฝ๋Š” ์ค‘์— ์ˆ˜์ • โ†’ ์ฝ๋˜ ๋‚ด์šฉ์ด ๋ฐ”๋€” ์œ„ํ—˜

๐Ÿ“Œ NLL (Non-Lexical Lifetimes)

Rust ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ฐธ์กฐ์˜ ๋งˆ์ง€๋ง‰ ์‚ฌ์šฉ ์‹œ์ ์„ ๊ธฐ์ค€์œผ๋กœ ํŒ๋‹จ:

let mut s = String::from("hello");
 
let r1 = &s;                         // โ”€โ”€ r1 ์‹œ์ž‘
let r2 = &s;                         // โ”€โ”€ r2 ์‹œ์ž‘
println!("{}, {}", r1, r2);          // โ”€โ”€ r1, r2 ๋ (๋งˆ์ง€๋ง‰ ์‚ฌ์šฉ)
 
let r3 = &mut s;                     // โœ… r1, r2 ์ด๋ฏธ ๋๋‚ฌ์œผ๋‹ˆ OK!
r3.push_str(", world");
println!("{}", r3);

ํ•ต์‹ฌ: ์ฝ๊ธฐ๊ฐ€ ๋๋‚œ ํ›„ ์ˆ˜์ •ํ•˜๋Š” ๊ฑด ์•ˆ์ „ โ†’ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ํ—ˆ์šฉ


๐Ÿ“Œ Dangling Reference ๋ฐฉ์ง€

// โŒ ํ•จ์ˆ˜ ๋‚ด๋ถ€ ๋ณ€์ˆ˜์˜ ์ฐธ์กฐ๋ฅผ ๋ฐ˜ํ™˜ โ†’ s๊ฐ€ drop๋˜๋ฉด ๋ฌดํšจ!
fn dangle() -> &String {
    let s = String::from("hello");
    &s  // s๊ฐ€ ํ•จ์ˆ˜ ๋์—์„œ ์‚ฌ๋ผ์ง โ†’ ๊ฐ€๋ฆฌํ‚ฌ ๋Œ€์ƒ ์—†์Œ!
}
 
// โœ… ์†Œ์œ ๊ถŒ ์ž์ฒด๋ฅผ ๋ฐ˜ํ™˜
fn no_dangle() -> String {
    let s = String::from("hello");
    s  // ์†Œ์œ ๊ถŒ์ด ํ˜ธ์ถœ์ž์—๊ฒŒ ์ด๋™
}

C/C++์—์„œ๋Š” dangling pointer๊ฐ€ ๋Ÿฐํƒ€์ž„ ๋ฒ„๊ทธ๋กœ ์ด์–ด์ง€์ง€๋งŒ, Rust๋Š” ์ปดํŒŒ์ผ ๋‹จ๊ณ„์—์„œ ์ฐจ๋‹จ


๐Ÿ“Œ ์‹ค์ „ ํŒจํ„ด: ํ•จ์ˆ˜์—์„œ์˜ Borrowing

fn average(scores: &Vec<f64>) -> f64 {       // & โ†’ ์ฝ๊ธฐ๋งŒ
    let sum = scores.iter().sum::<f64>();
    sum / scores.len() as f64
}
 
fn highest(scores: &Vec<f64>) -> f64 {        // & โ†’ ์ฝ๊ธฐ๋งŒ
    *scores.iter()
        .max_by(|a, b| a.partial_cmp(b).unwrap())
        .unwrap()
}
 
fn add_score(scores: &mut Vec<f64>, score: f64) {  // &mut โ†’ ์ˆ˜์ • ํ•„์š”
    scores.push(score);
}
 
fn main() {
    let mut scores = vec![85.0, 92.0, 78.0, 95.0, 88.0];
    
    println!("ํ‰๊ท : {}", average(&scores));       // ์ฝ๊ธฐ
    println!("์ตœ๊ณ : {}", highest(&scores));       // ์ฝ๊ธฐ
    add_score(&mut scores, 100.0);                // ์ˆ˜์ •
    println!("์ถ”๊ฐ€ ํ›„ ํ‰๊ท : {}", average(&scores)); // ๋‹ค์‹œ ์ฝ๊ธฐ
    println!("์ „์ฒด ์ ์ˆ˜: {:?}", scores);           // ์†Œ์œ ๊ถŒ ์œ ์ง€๋จ!
}

์›์น™: ์ˆ˜์ •์ด ํ•„์š”ํ•œ ํ•จ์ˆ˜๋งŒ &mut, ๋‚˜๋จธ์ง€๋Š” &๋กœ ์ตœ์†Œ ๊ถŒํ•œ ๋ถ€์—ฌ


๐Ÿ“Š ์ „์ฒด ๊ทœ์น™ ์š”์•ฝํ‘œ

๊ทœ์น™๋‚ด์šฉ์ด์œ 
&T ์—ฌ๋Ÿฌ ๊ฐœโœ… ๋™์‹œ OK์ฝ๊ธฐ๋ผ๋ฆฌ๋Š” ์•ˆ์ „
&mut T 1๊ฐœ๋งŒโŒ ๋™์‹œ์— 2๊ฐœ ๋ถˆ๊ฐ€๋™์‹œ ์ˆ˜์ • โ†’ ์ถฉ๋Œ ๋ฐฉ์ง€
&T + &mut TโŒ ๋™์‹œ ๋ถˆ๊ฐ€์ฝ๋Š” ์ค‘ ์ˆ˜์ • โ†’ ๋ฐ์ดํ„ฐ ๊นจ์ง ๋ฐฉ์ง€
NLL๋งˆ์ง€๋ง‰ ์‚ฌ์šฉ ์‹œ์  ๊ธฐ์ค€๋ถˆํ•„์š”ํ•œ ์ œ์•ฝ ์™„ํ™”
Dangling ๊ธˆ์ง€์‚ฌ๋ผ์ง„ ๋ฐ์ดํ„ฐ ์ฐธ์กฐ ๋ถˆ๊ฐ€๋ฌดํšจ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ ๋ฐฉ์ง€

โœ… ๋งˆ์Šคํ„ฐ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

  • "ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ mutable reference๋งŒ" ๊ทœ์น™์˜ ์ด์œ  ์„ค๋ช…
  • "mutable๊ณผ immutable reference ๋™์‹œ ์‚ฌ์šฉ ๋ถˆ๊ฐ€" ์ด์œ  ์„ค๋ช…
  • Dangling reference๊ฐ€ ์™œ ์œ„ํ—˜ํ•œ์ง€, Rust๋Š” ์–ด๋–ป๊ฒŒ ๋ฐฉ์ง€ํ•˜๋Š”์ง€
  • ์ปดํŒŒ์ผ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๊ณ  borrowing ๋ฌธ์ œ ํŒŒ์•… ๊ฐ€๋Šฅ
  • Reference๊ฐ€ ์–ธ์ œ "drop"๋˜๋Š”์ง€ ์ดํ•ด (NLL)

๐Ÿ”— ์ฐธ๊ณ  ์ž๋ฃŒ


๐Ÿš€ ๋‹ค์Œ ๋‹จ๊ณ„

Day 9-10: Structs & Methods โ€” &self, &mut self ํŒจํ„ด์œผ๋กœ ์˜ค๋Š˜ ๋ฐฐ์šด borrowing์„ ๊ตฌ์กฐ์ฒด์— ์ ์šฉ