Skip to content

Latest commit

ย 

History

History
508 lines (400 loc) ยท 24.5 KB

06_smart_pointer.md

File metadata and controls

508 lines (400 loc) ยท 24.5 KB

๋ฐ์ดํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ

์ผ๋ฐ˜ ํฌ์ธํ„ฐ๋Š” ๋‹จ์ˆœํžˆ ๋ฐ์ดํ„ฐ์˜ ์ฃผ์†Œ๋ฅผ ๊ฐ€์ง€๋Š” ํƒ€์ž…์ด์ง€๋งŒ, ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋Š” ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋‚˜ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ๊ธฐ๋Šฅ์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋Š” ํŠธ๋ ˆ์ดํŠธ์™€ ์ œ๋„ค๋ฆญ์„ ํ™œ์šฉํ•ด์„œ ๊ตฌํ˜„๋˜๊ธฐ ๋•Œ๋ฌธ์— ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋ฅผ ์ž˜ ํ™œ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํŠธ๋ ˆ์ดํŠธ์™€ ์ œ๋„ค๋ฆญ์„ ์ž˜ ์ดํ•ดํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋Š” ์‚ฌ์‹ค์€ ์ผ๋ฐ˜์ ์ธ ๊ตฌ์กฐ์ฒด์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‹ค์Œ 2๊ฐœ์˜ ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ž๋™์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๊ฒŒ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  1. Deref ํŠธ๋ ˆ์ดํŠธ: ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋‚˜ ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ์ฝ์–ด์„œ ์›๋ณธ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์ด ์—ญ์ฐธ์กฐ(Dereference)์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋Š” ์‚ฌ์‹ค์ƒ ๊ตฌ์กฐ์ฒด๋ผ๊ณ  ๋ง์”€๋“œ๋ ธ์Šต๋‹ˆ๋‹ค. ๊ตฌ์กฐ์ฒด๋Š” ํฌ์ธํ„ฐ๊ฐ€ ์•„๋‹ˆ๋‹ˆ ๊ตฌ์กฐ์ฒด๋ฅผ ํ†ตํ•ด์„œ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜๋ ค๋ฉด ๋ญ”๊ฐ€ ์ถ”๊ฐ€์ ์ธ ๊ตฌํ˜„์ด ํ•„์š”ํ•˜๊ฒ ์ง€์š”. ์ด๊ฒŒ ๋ฐ”๋กœ Deref ํŠธ๋ ˆ์ดํŠธ์ž…๋‹ˆ๋‹ค. *์™€ ๊ฐ™์€ ์—ญ์ฐธ์กฐ ์—ฐ์‚ฐ์ž๋ฅผ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์™€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. ์ž ์‹œ ํ›„์— ์ง์ ‘ ๊ตฌํ˜„ํ•ด๋ณด๋ฉด์„œ ๋‹ค์‹œ ์ด์•ผ๊ธฐํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
  2. Drop ํŠธ๋ ˆ์ดํŠธ: ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋Š” ์ž์‹ ์˜ ์Šค์ฝ”ํ”„๋ฅผ ๋ฒ—์–ด๋‚˜๊ฒŒ๋˜๋ฉด ์ž๋™์œผ๋กœ ํ•ด์ง€๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋Ÿฌ์ŠคํŠธ๋Š” ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๊ฐ€ ์Šค์ฝ”ํ”„๋ฅผ ๋ฒ—์–ด๋‚˜๋ฉด Drop ํŠธ๋ ˆ์ดํŠธ์˜ drop ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์„œ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํ•ด์ง€ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ์™ธ์—๋„ ํŒŒ์ผ์„ ๋‹ซ๊ฑฐ๋‚˜ํ•˜๋Š” ์ž์› ์ •๋ฆฌ ๊ธฐ๋Šฅ๋“ค์„ ์‹คํ–‰ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ž ์‹œ ํ›„์— ์ง์ ‘ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ๋ฅผ ํž™ ์˜์—ญ์— ์ €์žฅํ•˜๋Š” Box<T>

์Šค๋งˆํŠธ ํฌ์ธํ„ฐ ํƒ€์ž…์ด ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค๋งŒ ๊ฐ€์žฅ ํ•ต์‹ฌ์ ์ธ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋Š” Box<T>ํƒ€์ž…์ž…๋‹ˆ๋‹ค. <T>๋ผ๋Š” ํ‘œ์‹œ๋Š” ์ด ๋ฐ์ดํ„ฐ ํƒ€์ž… ๋‚ด๋ถ€์— ์ €์žฅ๋˜๋Š” ํƒ€์ž…์ด ์ œ๋„ค๋ฆญ ํƒ€์ž…์ด๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ž์‹ ์ด ์›ํ•˜๋Š” ์–ด๋–ค ๋ฐ์ดํ„ฐ ํƒ€์ž…๋„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

Box<T>์˜ ๊ฐ€์žฅ ํ•ต์‹ฌ์ ์ธ ์—ญํ• ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํž™ ์˜์—ญ์— ์ €์žฅํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ ๋Ÿฌ์ŠคํŠธ ์–ธ์–ด์—์„œ ์•„์ฃผ ์ค‘์š”ํ•œ ๊ฐœ๋…์ด ๋‚˜์˜ต๋‹ˆ๋‹ค. ๋Ÿฌ์ŠคํŠธ ์–ธ์–ด๋กœ ๊ฐœ๋ฐœํ•˜๊ธฐ์œ„ํ•ด์„œ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ํž™ ์˜์—ญ์— ์ €์žฅ๋˜๋Š๋ƒ ์Šคํƒ ์˜์—ญ์— ์ €์žฅ๋˜๋Š๋ƒ๋ฅผ ํ•ญ์ƒ ์ƒ๊ฐํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์Šคํƒ๊ณผ ํž™ ์˜์—ญ์€ ๋˜‘๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ์ด์ง€๋งŒ ์•„์ฃผ ์ค‘์š”ํ•œ ์ฐจ์ด์ ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์Šคํƒ ์˜์—ญ: ๋ฐ์ดํ„ฐ์˜ ํฌ๊ธฐ๋ฅผ ์ปดํŒŒ์ผ ์‹œ์ ์— ์•Œ ์ˆ˜ ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ํ•จ์ˆ˜ ํ˜ธ์ถœ์— ๊ด€ํ•œ ์Šคํƒ ํ”„๋ ˆ์ž„์„ ๋งŒ๋“œ๋Š” ์ปดํŒŒ์ผ ์‹œ์ ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ๋ฉ”๋ชจ๋ฆฌ ํฌ๊ธฐ๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ฐ์ดํ„ฐ์˜ ํฌ๊ธฐ๋Š” ๋ณ€ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์Šคํƒ์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ์˜ ํฌ๊ธฐ๊ฐ€ ๋Š˜์–ด๋‚œ๋‹ค๋ฉด ์Šคํƒ ํ”„๋ ˆ์ž„์€ ๋ง๊ฐ€์ ธ๋ฒ„๋ฆด ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋Œ€ํ‘œ์ ์œผ๋กœ u32๊ฐ™์€ ๊ธฐ๋ณธ ํƒ€์ž…๋“ค์€ ํ•ญ์ƒ ํฌ๊ธฐ๊ฐ€ ๊ณ ์ •๋˜์–ด์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋”ฐ๋กœ ์Šคํƒ์— ์ €์žฅ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ํž™ ์˜์—ญ: ๋ฐ์ดํ„ฐ์˜ ํฌ๊ธฐ๋ฅผ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์•Œ ์ˆ˜ ์—†๊ณ , ํ”„๋กœ๊ทธ๋žจ์ด ๋™์ž‘ํ•˜๋˜ ์ค‘์— ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ์˜ ํฌ๊ธฐ๊ฐ€ ๋ฐ”๋€” ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ Box<T>์˜ ๋™์ž‘ ๋ฐฉ์‹์„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์†Œ์œ ๊ถŒ ๊ด€๋ฆฌ: Box<T>๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ์˜ ํƒ€์ž…์ด ๋ฌด์—‡์ด๋“  ์ƒ๊ด€์—†์ด ๋ฐ์ดํ„ฐ๋ฅผ ํž™ ์˜์—ญ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ์™€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์Šคํƒ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์ˆœ์ˆ˜ํ•˜๊ฒŒ Box๋ผ๋Š” ๊ตฌ์กฐ์ฒด ํƒ€์ž…์ด ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด Box๋ผ๋Š” ๊ตฌ์กฐ์ฒดํƒ€์ž…์˜ ๊ฐ ํ•„๋“œ๋Š” ๊ณ ์ •๋œ ํฌ๊ธฐ๋ฅผ ๊ฐ€์ง€๋Š” ํ•„๋“œ๋“ค์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ Box๋ผ๋Š” ๊ตฌ์กฐ์ฒด์˜ ๊ฐ์ฒด๋Š” ์Šคํƒ์— ์ €์žฅ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  T๋ผ๋Š” ๋ฐ์ดํ„ฐ๋Š” ํž™ ์˜์—ญ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. Box๋Š” T์˜ ํฌ์ธํ„ฐ์™€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Boxํƒ€์ž…์˜ ๊ฐ์ฒด์˜ ์†Œ์œ ๊ถŒ์ด ์ด๋™ํ•˜๊ฒŒ๋˜๊ณ , ์ตœ์ข…์ ์œผ๋กœ Box ๊ฐ์ฒด์˜ ์†Œ์œ ๊ถŒ์ด ์‚ฌ๋ผ์ ธ์„œ ํ•ด์ง€๋  ๋•Œ Drop ํŠธ๋ ˆ์ดํŠธ๊ฐ€ ์‚ฌ์šฉ๋˜์–ด์„œ Tํƒ€์ž…์˜ ๊ฐ์ฒด๋„ ๊ฐ™์ด ํ•ด์ง€๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  2. ๋ฉ”๋ชจ๋ฆฌ ์—ญ์ฐธ์กฐ: Box ๊ฐ์ฒด ์•ˆ์— ํฌ์ธํ„ฐ๊ฐ€ ๋“ค์–ด์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. *๋ผ๋Š” ์—ญ์ฐธ์กฐ ์—ฐ์‚ฐ์ž๋Š” ์‚ฌ์‹ค ํฌ์ธํ„ฐ ํƒ€์ž…์— ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Box๋ผ๋Š” ๊ตฌ์กฐ์ฒด์— ์‚ฌ์šฉํ•˜๋ฉด ์•„๋ฌด๊ฒƒ๋„ ์•ˆ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ Deref ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์—ญ์ฐธ์กฐ ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ Deref ํŠธ๋ ˆ์ดํŠธ๋ฅผ ํ†ตํ•ด์„œ ํž™ ์˜์—ญ์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

์‚ฌ์šฉ๋ฒ•์€ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. Box๋ผ๋Š” ๊ตฌ์กฐ์ฒด์˜ new ๋ฉ”์†Œ๋“œ์— ์ž์‹ ์ด ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š”๊ฒƒ ๋ฟ์ž…๋‹ˆ๋‹ค.

fn main() {
    let my_data = Box::new(10);
    println!("What is in the heap?: {}", my_data);
}
$ cargo run
   Compiling pyalgo v0.1.0 (/Users/user/study/pyalgo)
    Finished dev [unoptimized + debuginfo] target(s) in 0.88s
     Running `target/debug/pyalgo`
What is in the heap?: 10

๊ทธ๋Ÿผ my_data๋ผ๋Š” ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๊ฐ€ ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. my_data๋ผ๋Š” Box<i32>ํƒ€์ž… ๊ตฌ์กฐ์ฒด๋Š” ์Šคํƒ์— ์ƒ์„ฑ๋˜์—ˆ๊ณ , 10์ด ์ €์žฅ๋œ i32ํƒ€์ž… ๋ฐ์ดํ„ฐ๋Š” ํž™์— ์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํฌ๊ฒŒ ์ค‘์š”ํ•œ๊ฑด ์•„๋‹ˆ์ง€๋งŒ ํ•œ๊ฐ€์ง€ ๋” ์‹คํ—˜์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. my_data๊ฐ€ ์Šคํƒ์— ์ €์žฅ๋˜์–ด์žˆ๊ณ , i32ํƒ€์ž… ๋ฐ์ดํ„ฐ๊ฐ€ ํž™์— ์ €์žฅ๋˜์–ด์žˆ๋Š” ๊ฒƒ์„ ์ฆ๋ช…ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์˜ˆ์ œ๋ฅผ ์‹คํ–‰ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

fn main() {
    let my_data = Box::new(10);
    println!("What is in the heap?: {}", my_data);
    println!("At stack: {:p}", &my_data);
    println!("At heap: {:p}", my_data.as_ref());
}
$ cargo run
   Compiling pyalgo v0.1.0 (/Users/user/study/pyalgo)
    Finished dev [unoptimized + debuginfo] target(s) in 0.88s
     Running `target/debug/pyalgo`
What is in the heap?: 10
At stack: 0x7ffef0c2e9b8
At heap: 0x5d21262e2b80

๊ฒฐ๊ณผ๊ฐ’์„ ๋ณด๋ฉด my_data๋ผ๋Š” ๋ณ€์ˆ˜๊ฐ€ ์œ„์น˜ํ•œ ๊ณณ์˜ ์ฃผ์†Œ๊ฐ’์ด 0x7ffef0c2e9b8์ด๊ณ  Box์˜ as_ref๋ฉ”์†Œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ๊ฐ’์ด 0x5d21262e2b80์ž…๋‹ˆ๋‹ค. as_ref๋Š” ๋ฉ”๋‰ด์–ผ์„ ์ฐพ์•„๋ณด๋ฉด Box<T>์—์„œ &T๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๊ณ  ์จ์žˆ์Šต๋‹ˆ๋‹ค. ํž™์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ์˜ ํฌ์ธํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฆฌ๋ˆ…์Šค์—์„œ๋Š” ์ด ๋ฉ”๋ชจ๋ฆฌ ๊ฐ’์œผ๋กœ ํž™์ธ์ง€ ์Šคํƒ์ธ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์™€๊ฐ™์ด ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ ์ถœ๋ ฅํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

$ cat /proc/$$/maps
563bb63d6000-563bb6404000 r--p 00000000 fc:02 16909610                   /usr/bin/bash
563bb6404000-563bb64df000 r-xp 0002e000 fc:02 16909610                   /usr/bin/bash
563bb64df000-563bb6518000 r--p 00109000 fc:02 16909610                   /usr/bin/bash
563bb6518000-563bb651c000 r--p 00141000 fc:02 16909610                   /usr/bin/bash
563bb651c000-563bb6525000 rw-p 00145000 fc:02 16909610                   /usr/bin/bash
563bb6525000-563bb6530000 rw-p 00000000 00:00 0
563bb7090000-563bb71d1000 rw-p 00000000 00:00 0                          [heap]
...์ƒ๋žต
7fffdb5c4000-7fffdb5e5000 rw-p 00000000 00:00 0                          [stack]
7fffdb5f2000-7fffdb5f6000 r--p 00000000 00:00 0                          [vvar]
7fffdb5f6000-7fffdb5f8000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]

์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜๋งˆ๋‹ค ์„ธ๋ถ€ ๊ฐ’๋“ค์€ ๋‹ค๋ฅด์ง€๋งŒ ์ œ๊ฐ€ ์‹คํ–‰ํ•œ ์‰˜์˜ ์Šคํƒ ์˜์—ญ์˜ ์ฃผ์†Œ๊ฐ’์€ 7fffdb5c4000-7fffdb5e5000์ด๊ณ , ํž™ ์˜์—ญ์˜ ์ฃผ์†Œ๊ฐ’์€ 55fb3f245000-55fb3f4a9000์ธ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์˜ˆ์ œ์˜ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ๊ณผ ์ •ํ™•ํ•œ ๊ฐ’์€ ๋‹ค๋ฅด๊ฒ ์ง€๋งŒ, ๋ชจ๋“  ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์Šคํƒ ์˜์—ญ์˜ ์ฃผ์†Œ๊ฐ’์ด 0x7fff๋กœ ์‹œ์ž‘ํ•˜๊ณ  ํž™ ์˜์—ญ์˜ ์ฃผ์†Œ๊ฐ’์ด 0x55fb๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์€ ๋‹ค๋ฅด์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๋ฆฌ๋ˆ…์Šค ์ปค๋„์ด ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•  ๋•Œ ๊ทธ๋ ‡๊ฒŒ ์ง€์ •ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์–ด์จŒ๋“  ๊ฒฐ๋ก ์ ์œผ๋กœ ์˜ˆ์ œ๋ฅผ ์‹คํ–‰ํ•ด๋ณด๋ฉด Box๋ผ๋Š” ๋ฐ์ดํ„ฐ ํƒ€์ž…์€ ์Šคํƒ ์˜์—ญ์— ์กด์žฌํ•˜๊ณ , ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฐ์ดํ„ฐ๋Š” ํž™ ์˜์—ญ์— ์กด์žฌํ•˜๊ณ  ์žˆ์Œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Box<T>๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•ด๋ณด๊ธฐ

Box<T>๋ฅผ ์ž˜ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ ์•„์ฃผ ๋‹จ์ˆœํ•œ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋ฅผ ์ง์ ‘ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. Box<T>๋Š” ๋‹ค์–‘ํ•œ ๋ฉ”์†Œ๋“œ๋“ค์ด ์žˆ์ง€๋งŒ, ์šฐ๋ฆฌ๋Š” ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์˜ ๊ฐ€์žฅ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์ธ ์—ญ์ฐธ์กฐ์™€ ์ž๋™ ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ง€๋งŒ์„ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

// src/smart_pointer_basic/main.rs
use std::ops::{Deref, DerefMut};

struct MySmartPointer<T>(T);

impl<T> MySmartPointer<T> {
    fn new(x: T) -> MySmartPointer<T> {
        MySmartPointer(x)
    }
}

impl<T> Deref for MySmartPointer<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.0
    }
}

impl<T> DerefMut for MySmartPointer<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

impl<T> Drop for MySmartPointer<T> {
    fn drop(&mut self) {
        println!("Dropping MySmartPointer");
    }
}

fn main() {
    let my_pointer = MySmartPointer::new(5);
    println!("Value: {}", *my_pointer);
    let mut mut_pointer = MySmartPointer::new(1);
    *mut_pointer = 2;
    println!("Value: {}", *mut_pointer);
}
$ cargo run --bin smart_pointer_basic
   Compiling my-rust-book v0.1.0 (/home/gkim/study/my-rust-book)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.15s
     Running `target/debug/smart_pointer_basic`
Value: 5
Value: 2
Dropping MySmartPointer
Dropping MySmartPointer

๊ฐ€์žฅ ๋จผ์ € Deref, DerefMut ๋‘๊ฐ€์ง€ ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๋„๋ก ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.

use std::ops::{Deref, DerefMut};

๊ทธ๋ฆฌ๊ณ  MySmartPointer๋ผ๋Š” ๊ตฌ์กฐ์ฒด๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ œ๋„ค๋ฆญ์„ ์‚ฌ์šฉํ•ด์„œ ์ œ๋„ค๋ฆญ ํƒ€์ž…์€ T์ž…๋‹ˆ๋‹ค. ๊ตฌ์กฐ์ฒด ์ž์ฒด๋Š” ๊ฐ€์žฅ ๋‹จ์ˆœํ•˜๊ฒŒ ๋ฐ์ดํ„ฐ๋งŒ ํฌํ•จํ•˜๋„๋ก ๋งŒ๋“ญ๋‹ˆ๋‹ค.

struct MySmartPointer<T>(T);

์‚ฌ์‹ค์€ ์ด ๊ตฌ์กฐ์ฒด๋Š” ์Šค๋งˆํŠธํฌ์ธํ„ฐ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ํž™์— ์ €์žฅํ•˜๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ ์Šคํƒ์— ์ €์žฅํžˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํž™์— ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹นํ•˜๊ธฐ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์†Œ๊ฐœํ•˜์ง€์•Š์•˜์œผ๋‹ˆ ํ‰๋‚ด๋งŒ ๋‚ด๊ธฐ ์œ„ํ•ด์„œ ์Šคํƒ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

MySmartPointer๋ฅผ ์ƒ์„ฑํ•˜๋Š” new ๋ฉ”์†Œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ x๋ฅผ ๋ฐ›์•„์„œ ๊ทธ๋Œ€๋กœ ์ €์žฅํ•  ๋ฟ์ž…๋‹ˆ๋‹ค.

impl<T> MySmartPointer<T> {
    fn new(x: T) -> MySmartPointer<T> {
        MySmartPointer(x)
    }
}

์ด์ œ Deref ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

impl<T> Deref for MySmartPointer<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.0
    }
}

deref๋ผ๋Š” ๋ฉ”์†Œ๋“œ๊ฐ€ ์žˆ๋Š”๋ฐ ์Šค๋งˆํŠธํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฐ์ดํ„ฐ์˜ ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ๊ตฌํ˜„ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด *์—ฐ์‚ฐ์ž์™€ ๊ฒฐํ•จํ•ด์„œ *&T๊ฐ€ ๋˜๋ฏ€๋กœ ๊ฒฐ๊ตญ ํž™์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ฒŒ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ์€ DerefMut ํŠธ๋ ˆ์ดํŠธ์ž…๋‹ˆ๋‹ค. mut์ด๋ผ๋Š” ์ด๋ฆ„์ด ๋ถ™์€ ๊ฒƒ์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋Š” mutable ๋ ˆํผ๋Ÿฐ์Šค &mut T๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ค๋‹ˆ๋‹ค.

impl<T> DerefMut for MySmartPointer<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

DerefMutํŠธ๋ ˆ์ดํŠธ์˜ ์‚ฌ์šฉ๋ฒ•์€ mainํ•จ์ˆ˜์—์„œ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์€ Drop ํŠธ๋ ˆ์ดํŠธ์˜ ๊ตฌํ˜„์ž…๋‹ˆ๋‹ค.

impl<T> Drop for MySmartPointer<T> {
    fn drop(&mut self) {
        println!("Dropping MySmartPointer");
    }
}

์‚ฌ์‹ค ์šฐ๋ฆฌ ๋ฐ์ดํ„ฐ๋Š” ์Šคํƒ์— ์ €์žฅ๋˜๋ฏ€๋กœ ์‹ค์ œ๋กœ ํ•˜๋Š” ์ผ์€ ์—†์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํž™์— ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ–ˆ์œผ๋ฉด, drop ๋ฉ”์†Œ๋“œ์—์„œ ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ง€๋ฅผ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์€ mainํ•จ์ˆ˜๋ฅผ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋จผ์ € DerefํŠธ๋ ˆ์ดํŠธ๋ฅผ ์ด์šฉํ•ด์„œ ์Šค๋งˆํŠธํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ธฐ๋งŒ ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

fn main() {
    let my_pointer = MySmartPointer::new(5);
    println!("Value: {}", *my_pointer);

my_pointer๋Š” ํฌ์ธํ„ฐ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ *์—ฐ์‚ฐ์ž๋ฅผ ๋ถ™์ด๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ DerefํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜์ง€์•Š์•˜์œผ๋ฉด ๊ทธ๋ƒฅ ์ผ๋ฐ˜ ๊ตฌ์กฐ์ฒด ์ด๋ฆ„์— *๋ฅผ ๋ถ™์ธ ๊ฒƒ์ด๋ฏ€๋กœ ์•„๋ฌด ๋™์ž‘๋„ ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ ๋‹ค์Œ์—๋Š” DerefMut ํŠธ๋ ˆ์ดํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

    let mut mut_pointer = MySmartPointer::new(1);
    *mut_pointer = 2;
    println!("Value: {}", *mut_pointer);
}

mut_pointer๋ผ๋Š” ๋ณ€์ˆ˜๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ”๋€” ๊ฒƒ์ด๋ฏ€๋กœ ๋ฐ˜๋“œ์‹œ mut ์„ ์–ธ์ด ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”๊พธ๋Š” ๋ฐฉ๋ฒ•์€ ํฌ์ธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. "*ํฌ์ธํ„ฐ์ด๋ฆ„" ํ˜•ํƒœ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋งˆ์ง€๋ง‰์œผ๋กœ mainํ•จ์ˆ˜์˜ ์Šค์ฝ”ํ”„๊ฐ€ ๋๋‚˜๋ฉด ๋‘๊ฐœ์˜ ์Šค๋งˆํŠธํฌ์ธํŠธ๊ฐ€ ๋ชจ๋‘ ์‚ฌ๋ผ์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋•Œ Drop ํŠธ๋ ˆ์ดํŠธ์˜ drop ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

Box ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋ฅผ ํ™œ์šฉํ•˜๋Š” ์˜ˆ์ œ

์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํž™ ์˜์—ญ์— ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ์˜ ํฌ๊ธฐ๊ฐ€ ํฌ๊ฑฐ๋‚˜ ๋™์ ์œผ๋กœ ๋ฐ์ดํ„ฐ์˜ ํฌ๊ธฐ๊ฐ€ ๋ณ€ํ•œ๋‹ค๋ฉด ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋ฐ–์— ์—†์Šต๋‹ˆ๋‹ค. ๋Œ€ํ‘œ์ ์œผ๋กœ ๋„คํŠธ์›Œํฌ๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ค๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ์˜ ํฌ๊ธฐ๋„ ํด ๊ฒƒ์ด๊ณ , ๋ฐ์ดํ„ฐ์˜ ํฌ๊ธฐ๊ฐ€ ์–ผ๋งˆ๋‚˜๋ ์ง€๋Š” ์ปดํŒŒ์ผ ์‹œ์ ์—๋Š” ์ ˆ๋Œ€ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ทธ ์™ธ์— Box<T>๋ผ๋Š” ํƒ€์ž…์„ ๋ฐ˜๋“œ์‹œ ์‚ฌ์šฉํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ํ•˜๋‚˜ ๋” ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ „์— ํŠธ๋ ˆ์ดํŠธ๋ฅผ ์„ค๋ช…ํ•  ๋•Œ ํŠธ๋ ˆ์ดํŠธ ๊ฐ์ฒด์— ๋Œ€ํ•ด์„œ ์ด์•ผ๊ธฐํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ํ•œ๋ฒˆ ์ด์•ผ๊ธฐํ•˜๋ฉด ์–ด๋–ค ํ•จ์ˆ˜๊ฐ€ ํŠน์ •ํ•œ ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•œ ํƒ€์ž…๋งŒ์„ ์ „๋‹ฌ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๊ฐœ์˜ ๊ตฌ์กฐ์ฒด๊ฐ€ ์žˆ๋Š”๋ฐ ๋ชจ๋‘ A๋ผ๋Š” ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ ์ด ๊ตฌ์กฐ์ฒด๋“ค์„ ๋ฒกํ„ฐ๋‚˜ ๋ฐฐ์—ด์— ๋ชจ์•„๋†“๊ณ  ์‹ถ์„ ๋•Œ๊ฐ€ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด์„œ GenSerialData๋ผ๋Š” ํŠน์ •ํ•œ ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•œ ํƒ€์ž…๋“ค์„ ํ•˜๋‚˜์˜ ๋ฒกํ„ฐ์— ๋ชจ์•„์„œ ํ•œ๊บผ๋ฒˆ์— ์ฒ˜๋ฆฌ๋˜๋„๋ก ๋งŒ๋“ค๊ณ  ์‹ถ์œผ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

use std::io::{stdin, stdout, Write};

fn get_user_input() -> String {
    let mut s = String::new();
    let _ = stdout().flush();
    stdin()
        .read_line(&mut s)
        .expect("Did not enter a correct string");
    if let Some('\n') = s.chars().next_back() {
        s.pop();
    }
    if let Some('\r') = s.chars().next_back() {
        s.pop();
    }
    s
}

trait GenSerialData {
    fn get_input(&mut self);
    fn generate(&self) -> Option<&str>;
}

struct UserID {
    digit: u32,
    id: Option<String>,
}

impl GenSerialData for UserID {
    fn get_input(&mut self) {
        println!("Please input {}-digits User ID: ", self.digit);
        self.id = Some(get_user_input());
    }

    fn generate(&self) -> Option<&str> {
        self.id.as_ref().map(|x| x.as_str())
    }
}

struct ProductID {
    digit: u32,
    id: Option<String>,
}

impl GenSerialData for ProductID {
    fn get_input(&mut self) {
        println!("Please input {}-digits Product ID: ", self.digit);
        self.id = Some(get_user_input());
    }

    fn generate(&self) -> Option<&str> {
        self.id.as_ref().map(|x| x.as_str())
    }
}

fn collect_data(items: &mut [&dyn GenSerialData]) {
    for item in items.iter_mut() {
        item.get_input();
    }
}

fn generate_serial(items: &[&dyn GenSerialData]) -> String {
    let mut data = String::new();
    for item in items.iter() {
        data.push_str(item.generate().unwrap());
    }
    data
}

fn main() {
    let userid = UserID { digit: 4, id: None };
    let product = ProductID { digit: 8, id: None };

    let mut items = [&userid, &product];

    collect_data(&mut items);
    let serial = generate_serial(&items);
    println!("Serial generated: {}", serial);
}
$ cargo run --bin smart_pointer_application
   Compiling my-rust-book v0.1.0 (/home/gkim/study/my-rust-book)
error[E0308]: mismatched types
  --> src/smart_pointer_application/main.rs:73:31
   |
73 |     let mut items = [&userid, &product];
   |                               ^^^^^^^^ expected `&UserID`, found `&ProductID`
   |
   = note: expected reference `&UserID`
              found reference `&ProductID`

error[E0596]: cannot borrow `**item` as mutable, as it is behind a `&` reference
  --> src/smart_pointer_application/main.rs:57:9
   |
57 |         item.get_input();
   |         ^^^^ cannot borrow as mutable

Some errors have detailed explanations: E0308, E0596.
For more information about an error, try `rustc --explain E0308`.
error: could not compile `my-rust-book` (bin "smart_pointer_application") due to 2 previous errors

์ด ์˜ˆ์ œ๋Š” ์‚ฌ์šฉ์ž ID๊ณผ ์ œํ’ˆ ID๋ฅผ ์กฐํ•ฉํ•ด์„œ ์ œํ’ˆ์˜ ์‹œ๋ฆฌ์–ผ๋ฒˆํ˜ธ๋ฅผ ๋งŒ๋“œ๋Š” ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค. UserID๋ผ๋Š” ๊ตฌ์กฐ์ฒด์™€ ProductID๋ผ๋Š” ๊ตฌ์กฐ์ฒด๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ๋‘๊ฐ€์ง€ ๊ตฌ์กฐ์ฒด๋Š” ๋˜‘๊ฐ™์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๋Š” ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ (์•„๋งˆ๋„ ์ œํ’ˆ์„ ๊ด€๋ฆฌํ•˜๋Š” ์˜์—… ๋ถ€์„œ์˜ ์ง์›๋ ๊ฒƒ ๊ฐ™๋„ค์š”) ์ž…๋ ฅ์„ ๋ฐ›์•„์„œ ๋ฌธ์ž์—ด๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‹œ๋ฆฌ์–ผ ๋ฒˆํ˜ธ๋ฅผ ๋งŒ๋“ค ๋•Œ ์ž์‹ ์˜ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์ฃผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ GenSerialData๋ผ๋Š” ํŠธ๋ ˆ์ดํŠธ๋ฅผ UserID์™€ ProductID๊ฐ€ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜์ค‘์— ์‚ฌ์šฉ์žID์™€ ์ œํ’ˆID์™ธ์—๋„ ์ •์ˆ˜ํ˜•ํƒœ์˜ ์‚ฌ์šฉ ๋งŒ๊ธฐ ๋‚ ์งœ๋‚˜ ํŒ๋งค ๋‚ ์งœ ๋“ฑ ๋‹ค์–‘ํ•œ ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์‹œ๋ฆฌ์–ผ ๋ฒˆํ˜ธ์— ๋„ฃ์„ ์ˆ˜ ์žˆ๋„๋ก ํ™•์žฅ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ์˜ ํƒ€์ž…์„ ๋งŒ๋“ค๊ณ  GenSerialData๋ผ๋Š” ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋˜๋‹ˆ๊นŒ์š”.

ํ•ต์‹ฌ์ ์ธ ์—ญํ• ์„ ํ•˜๋Š” ํ•จ์ˆ˜๊ฐ€ ๋ฐ”๋กœ collect_data์™€ generate_serial ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

fn collect_data(items: &mut [&dyn GenSerialData]) {
    for item in items.iter_mut() {
        item.get_input();
    }
}

fn generate_serial(items: &[&dyn GenSerialData]) -> String {
    let mut data = String::new();
    for item in items.iter() {
        data.push_str(item.generate().unwrap());
    }
    data
}

ํŠธ๋ ˆ์ดํŠธ ๊ฐ์ฒด์˜ ๋ฐฐ์—ด์„ ์ „๋‹ฌ๋ฐ›์•„์„œ ๋ชจ๋“  ํŠธ๋ ˆ์ดํŠธ ๊ฐ์ฒด์˜ ๊ณตํ†ต ๋ฉ”์†Œ๋“œ get_input๊ณผ generate๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ์‹œ๋ฆฌ์–ผ ๋ฒˆํ˜ธ์— ๋“ค์–ด๊ฐ€์•ผ๋˜๋Š” ๋ชจ๋“  ๋ฐ์ดํ„ฐ ํƒ€์ž…์— ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ๊บผ์ „์— ์ž…๋ ฅํ•˜๊ณ  ์ถœ๋ ฅํ•˜๋Š” ๋ฃจํ”„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์œ ๊ฐ์Šค๋Ÿฝ๊ฒŒ๋„ ์ด ์˜ˆ์ œ ์ฝ”๋“œ๋Š” ๋นŒ๋“œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. userid์™€ productid์˜ ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ์ €์žฅํ•˜๋Š” items์—์„œ ๋นŒ๋“œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋ฐฐ์—ด์ด๋‚˜ ๋ฒกํ„ฐ๋Š” ๋™์ผํ•œ ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ์˜ˆ์ œ์—์„œ๋Š” ๋™์ผํ•œ ํƒ€์ž…์„ ์ €์žฅํ•˜๋Š”๊ฒŒ ์••๋‹ˆ๋‹ค. &userid๋Š” UserID ๊ตฌ์กฐ์ฒด ํƒ€์ž…์˜ ๋ ˆํผ๋Ÿฐ์Šค์ด๊ณ , &productid๋Š” ProductID์˜ ๋ ˆํผ๋Ÿฐ์Šค์ด๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋กœ ๋‹ค๋ฅธ ํƒ€์ž…์ž…๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ ๋ฐฐ์—ด์— ์ €์žฅ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋น„๋ก ๋‘ ๋ ˆํผ๋Ÿฐ์Šค๊ฐ€ ๋ชจ๋‘ ๊ฐ™์€ ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•œ ํƒ€์ž…์˜ ๋ ˆํผ๋Ÿฐ์Šค์ด์ง€๋งŒ, ๋™์ผํ•œ ํƒ€์ž…์€ ์•„๋‹™๋‹ˆ๋‹ค. ๊ฐ์ž ๋”ฐ๋กœ ํŠธ๋ ˆ์ดํŠธ ๊ฐ์ฒด๋กœ ์‚ฌ์šฉ๋  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ํ•˜๋‚˜์˜ ๋ฐฐ์—ด์— ์ €์žฅ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์ด ๋‘ ๊ฐ์ฒด๋ฅผ Box<T>์— ๋‹ด๋Š”๋‹ค๋ฉด ์ด์•ผ๊ธฐ๋Š” ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค. ๋ฐฐ์—ด์— ์ €์žฅ๋˜๋Š” ๊ฒƒ์€ Boxํƒ€์ž…์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ Box๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋ฐ”๊ฟ”๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

// src/smart_pointer_application/main.rs
use std::io::{stdin, stdout, Write};

fn get_user_input() -> String {
    let mut s = String::new();
    let _ = stdout().flush();
    stdin()
        .read_line(&mut s)
        .expect("Did not enter a correct string");
    if let Some('\n') = s.chars().next_back() {
        s.pop();
    }
    if let Some('\r') = s.chars().next_back() {
        s.pop();
    }
    s
}

trait GenSerialData {
    fn get_input(&mut self);
    fn generate(&self) -> Option<&str>;
}

struct UserID {
    digit: u32,
    id: Option<String>,
}

impl GenSerialData for UserID {
    fn get_input(&mut self) {
        println!("Please input {}-digits User ID: ", self.digit);
        self.id = Some(get_user_input());
    }

    fn generate(&self) -> Option<&str> {
        self.id.as_ref().map(|x| x.as_str())
    }
}

struct ProductID {
    digit: u32,
    id: Option<String>,
}

impl GenSerialData for ProductID {
    fn get_input(&mut self) {
        println!("Please input {}-digits Product ID: ", self.digit);
        self.id = Some(get_user_input());
    }

    fn generate(&self) -> Option<&str> {
        self.id.as_ref().map(|x| x.as_str())
    }
}

//fn collect_data(items: &mut Vec<Box<dyn GenSerialData>>) { // If you want to use Vec<Box<dyn GenSerialData>> in main function
fn collect_data(items: &mut [Box<dyn GenSerialData>]) {
    for item in items.iter_mut() {
        item.get_input();
    }
}

// &[&dyn GenSerialData] is wrong!
//fn generate_serial(items: &Vec<Box<dyn GenSerialData>>) -> String { // If you want to use Vec<Box<dyn GenSerialData>> in main function
fn generate_serial(items: &[Box<dyn GenSerialData>]) -> String {
    let mut data = String::new();
    for item in items.iter() {
        data.push_str(item.generate().unwrap());
    }
    data
}

fn main() {
    println!("hello");

    let userid = UserID { digit: 4, id: None };
    let productid = ProductID { digit: 8, id: None };

    // Vec<&dyn GenSerialData> is wrong!
    //let mut items: Vec<Box<dyn GenSerialData>> = vec![Box::new(userid), Box::new(productid)];
    let mut items: [Box<dyn GenSerialData>; 2] = [Box::new(userid), Box::new(productid)];

    collect_data(&mut items);
    let serial = generate_serial(&items);
    println!("Serial generated: {}", serial);
}
$ cargo run --bin smart_pointer_application
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/smart_pointer_application`
hello
Please input 4-digits User ID: 
1234
Please input 8-digits Product ID: 
qwerasdf
Serial generated: 1234qwerasdf

์ด์ „ ์˜ˆ์ œ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

fn collect_data(items: &mut [&dyn GenSerialData]) {
...
fn generate_serial(items: &[&dyn GenSerialData]) -> String {
...
    let mut items = [&userid, &product];

๋ฐฐ์—ด์„ ์‚ฌ์šฉํ–ˆ๋˜ ๋ชจ๋“  ํ•จ์ˆ˜ ์ธ์ž์™€ items ๋ณ€์ˆ˜ ์„ ์–ธ ๋ถ€๋ถ„์„ Box๋กœ ๋ฐ”๊ฟจ์Šต๋‹ˆ๋‹ค.

fn collect_data(items: &mut [Box<dyn GenSerialData>]) {
...
fn generate_serial(items: &[Box<dyn GenSerialData>]) -> String {
...
    let mut items: [Box<dyn GenSerialData>; 2] = [Box::new(userid), Box::new(productid)];

๊ทธ๋ฆฌ๊ณ  items์„ ๋ฐฐ์—ด์ด ์•„๋‹ˆ๋ผ ๋ฒกํ„ฐ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋ฒกํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

fn collect_data(items: &mut Vec<Box<dyn GenSerialData>>) { // If you want to use Vec<Box<dyn GenSerialData>> in main function
...
fn generate_serial(items: &Vec<Box<dyn GenSerialData>>) -> String { // If you want to use Vec<Box<dyn GenSerialData>> in main function
...
    let mut items: Vec<Box<dyn GenSerialData>> = vec![Box::new(userid), Box::new(productid)];

ํ•œ๊ฐ€์ง€ ์ฃผ์˜ํ•ด์•ผํ•  ๊ฒƒ์ด ํƒ€์ž… ์ง€์ •์„ ๋ฐ˜๋“œ์‹œ ํ•ด์•ผํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

    let mut items = vec![Box::new(userid), Box::new(productid)];
    let mut items = [Box::new(userid), Box::new(productid)];

๋งŒ์•ฝ ์œ„์™€ ๊ฐ™์ด ํƒ€์ž… ์ง€์ •์„ ์ง€์šด๋‹ค๋ฉด ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋ฐฐ์—ด์— UserID ํƒ€์ž…์˜ ํฌ์ธํ„ฐ๊ฐ€ ์ €์žฅ๋˜๋Š” ๊ฒƒ์ธ์ง€, ProductID ํƒ€์ž…์˜ ํฌ์ธํ„ฐ๊ฐ€ ์ €์žฅ๋˜์–ด์•ผํ•˜๋Š” ๊ฒƒ์ธ์ง€๋ฅผ ํŒ๋‹จํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋ฐ˜๋“œ์‹œ ํŠธ๋ ˆ์ดํŠธ ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•œ๋‹ค๊ณ  ํƒ€์ž…์„ ์จ์ฃผ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ ํƒ€์ž…๋“ค

๊ทธ ์™ธ์—๋„ ๋ช‡๊ฐ€์ง€ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๊ฐ€ ๋” ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ๊ธฐ ๋‹ค๋ฅธ ์šฉ๋„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋“ค์€ ๋ณดํ†ต ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด๋‚˜ ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ๋“ค์ด๋ผ์„œ ์ด ์ฑ…์—์„œ๋Š” ์ž์„ธํžˆ ์†Œ๊ฐœํ•˜์ง€ ์•Š๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐ„๋‹จํžˆ ์ด๋ฆ„๊ณผ ์šฉ๋„๋งŒ ์†Œ๊ฐœํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

  1. Rc<T>, Arc<T>: ์†Œ์œ ๊ถŒ์„ ์—ฌ๋Ÿฌ๊ฐœ ๋งŒ๋“ค์–ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Rc<T>๋Š” ์‹ฑ๊ธ€์“ฐ๋ ˆ๋“œ์—์„œ ํŠธ๋ฆฌ๋‚˜ ๊ทธ๋ž˜ํ”„์™€ ๊ฐ™์ด ์„œ๋กœ๊ฐ€ ์„œ๋กœ๋ฅผ ์ฐธ์กฐํ•˜๋Š” ํ˜•ํƒœ์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. Arc<T>๋Š” ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ์—์„œ ์—ฌ๋Ÿฌ ์“ฐ๋ ˆ๋“œ๊ฐ€ ๊ณต์œ ํ•˜๋Š” ๋ฐ์ดํ„ฐ์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  2. RefCell<T>: ์–ด๋–ค ๋ฐ์ดํ„ฐ์˜ ๋ถˆ๋ณ€ํ˜•(Immutable) ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ๊ฐ€์ง€๊ณ ์žˆ๋Š” ์ƒํ™ฉ์—์„œ๋„, ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •๊ฐ€๋Šฅํ•˜๋„๋ก ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค. ๋ณดํ†ต์€ ์ˆ˜์ •ํ•˜์ง€ ์•Š์ง€๋งŒ, ์ •๋ง ์˜ˆ์™ธ์ ์ธ ๊ฒฝ์šฐ์— ์ˆ˜์ •๊ฐ€๋Šฅํ•˜๋„๋ก ๋งŒ๋“ค์–ด์•ผ๋ ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  3. Cell<T>: ๊ฑฐ์˜ ์‚ฌ์šฉ๋  ์ผ์ด ์—†์ง€๋งŒ, ํŠน์ • ๊ฐ์ฒด์— ๋Œ€ํ•ด ์™„์ „ํžˆ ์ˆ˜์ •๊ฐ€๋Šฅํ•˜๋ฉด์„œ ๋™์‹œ์— ๊ณต์œ  ๊ฐ€๋Šฅํ•œ ํฌ์ธํ„ฐ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๋ณดํ†ต C/C++ ์–ธ์–ด์™€ ๋Ÿฌ์ŠคํŠธ ์–ธ์–ด๋ฅผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ๋•Œ C/C++์˜ ํฌ์ธํ„ฐ ๋ณ€์ˆ˜์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  4. Mutex<T>, RwLock<T>: ์ด๋ฆ„์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด ๋ฝ์„ ๊ตฌํ˜„ํ•œ ํƒ€์ž…๋“ค์ž…๋‹ˆ๋‹ค.