4.0 Ownership
์์ ๊ถ์ ๋ฌ์คํธ์ ๊ฐ์ฅ ํน์ง์ ์ธ ๊ฐ๋ ์ด๋ค, ๋ฌ์คํธ๋ฅผ ์ดํดํ๊ธฐ ์ํด์, ๋๋ ๋ฌ์คํธ๊ฐ ์ ๋ค๋ฅธ ์ธ์ด๋ค๋ณด๋ค ์ฃผ๋ชฉ๋ฐ๋์ง ์ดํดํ๊ธฐ ์ํด์ ๊ฐ์ฅ ์ค์ํ ์ฅ์ด๋ผ๊ณ ์๊ฐํ๋ค.
4.1.1 What is Ownership?
Ownership์ ๋ฌ์คํธ๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ด๋ฆฌํ๋ ๊ท์น์ด๋ค.
-
๋ชจ๋ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ด ์๋ค.
-
๊ฐ์ฅ ๋ํ์ ์ธ ๋ ๊ฐ๋๋ GC(Garbage Collection)์ ์๋ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ก ๋ณผ ์์๋ค.
-
GC๋ ํ๋ก๊ทธ๋จ์ด ์คํ๋๋๋์, ๋ ์ด์ ์ฌ์ฉํ์ง ์๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฐพ์๋ด๊ณ ํด์ฒดํ๋ ๋ฐฉ๋ฒ์ด๋ค.
-
์๋ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ ํ๋ก๊ทธ๋๋จธ๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ง์ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ด๋ค.
-
๋น์ฐํ GC๊ฐ ํธ๋ฆฌํ๊ณ ์์ ํ์ง๋ง, ์ฑ๋ฅ์ด ๋จ์ด์ง๋ค๋ ๋จ์ ์ด ์๋ค.
-
๋ฌ์คํธ๋ ์ธ๋ฒ์งธ ๋ฐฉ๋ฒ์ธ Ownership์ ์ฌ์ฉํ๋ค.
-
๊ฐ์ธ์ ์ผ๋ก Ownership์์ ๊ฐ์ฅ ์ค์ํ ํฌ์ธํธ๋ ‘๊ท์น’์ด๋ผ๊ณ ์๊ฐํ๋ค.
-
์์ ๊ถ์ด ์ ์ฉ๋๋ ๊ท์น์ ์์ฝํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
-
๊ฐ๊ฐ์ ๊ฐ์ ์์ ์(owner)๊ฐ ์๋ค.
-
ํ๋ฒ์ ํ๋์ ์์ ์๋ง ์กด์ฌํ ์ ์๋ค.
-
์์ ์๊ฐ ์ค์ฝํ๋ฅผ ๋ฒ์ด๋๋ฉด, ๊ฐ์ ํด์ ๋๋ค.
-
-
์ฌ์ค ์์ ํ ์๋ก์ด ๋ฐฉ์์ ์๋๋ค. C++์ RAII(Resource Acquisition Is Initialization)์ ๋น์ทํ ๊ฐ๋ ์ด๋ค.
-
RAII๋ ๊ฐ์ฒด๊ฐ ์์ฑ๋ ๋, ์์์ ํ ๋นํ๊ณ , ์๋ฉธ๋ ๋ ์์์ ํด์ ํ๋ ๋ฐฉ์์ด๋ค.
- ๊ฐ์ฒด์ ์์ฑ๊ณผ ์๋ฉธ์ ์์์ ํ ๋น๊ณผ ํด์ ๋ก ์ฐ๊ฒฐ์ง๋๋ค.
-
์ฐธ์กฐ๊ฐ ์์ผ๋ฉด(์ค์ฝํ๋ฅผ ๋๊ฐ๋ฉด) ์๋์ผ๋ก ํด์ ๋๋ค๋ ์ ์์๋ GC์ ๋น์ทํ๋ค.
- GC๋ฅผ ์์ฃผ ๋ฌด์ํ๊ฒ ์์ฝํ๋ฉด ์ฐธ์กฐ๊ฐ ์์ด์ง ๋งค๋ชจ๋ฆฌ๋ฅผ ์ฒดํฌํ๊ณ ํ์ํ๋ค๊ณ ํ ์ ์๋ค.
-
Rust๋’๊ท์น’์ ๊ธฐ๋ฐํ ์์ ๊ถ์ ์ฌ์ฉํ์ฌ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ด๋ฆฌํ๋ค, ๋ฐ๋๋ก ์๊ฐํ๋ฉด, ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ญ๋นํ๊ฑฐ๋ ์ํ์ ๋น ๋จ๋ฆฌ์ง ์๋ ‘๊ท์น์’ ๊ตฌํํ ๊ฒ์ ๋ ํฐ ์์๊ฐ ์๋ค.
-
๊ทธ์ ๋ํ ๋๊ฐ๋ก Rust๋ ์ปดํ์ผํ์์ ๋ฉ๋ชจ๋ฆฌ ์์ ์ฑ์ ๊ฒ์ฆ ํ ์ ์๊ณ , GC์ ๊ฐ์ด ๋ฐํ์์ ์ถ๊ฐ์ ์ธ ๋น์ฉ์ด ๋ฐ์ํ์ง ์๋๋ค.
-
๊ฒฐ๋ก ์ ์ผ๋ก ํ๋ก๊ทธ๋๋จธ๋ Rust์ Ownership์ด๋ผ๋ ๊ท์น์ ๋ฐ๋ฅด๋ฉฐ ํ๋ก๊ทธ๋๋ฐ์ ํ๋ ๊ฒ์ ์ด๋ ต์ง๋ง, ๊ทธ ๋๊ฐ๋ก ์์ ํ๋ฉด์๋ ๋น ๋ฅธ ํ๋ก๊ทธ๋จ์ ๋ง๋ค ์ ์๋ค.
4.1.2 Stack and Heap
Stack๊ณผ Heap์ ์ฐ๋ฆฌ์ ์ฝ๋๊ฐ ๋ฐํ์์ ์ฌ์ฉ ํ ์ ์๋ ๋ฉ๋ชจ๋ฆฌ์ด๋ค. ์คํ์ ์๋ฃ๊ตฌ์กฐ ์คํ์ ๊ฐ๋ ์ ๋ฐ๋ฅธ๋ค. LIFO๋ ๊ตณ์ด ์ค๋ช ์ํด๋ ๊ด์ฐฎ์ง๋ง, ํน์ ํ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์ผ๋ ฌ๋ก ๋์ด์ ์๋ ์ ํ ์๋ฃ๊ตฌ์กฐ์์ ์ธ์งํด์ผ ํ๋ค. ์๋๋ฉด ํ์ ์คํ๊ณผ ๋ค๋ฅด๊ฒ ๋ฉ๋ชจ๋ฆฌ์ ์ด๋ ๊ณณ์๋ ํ ๋นํ๊ณ , ์ฒซ์นธ์ ํฌ์ธํฐ๋ฅผ ๋ฐํ๋ฐ๊ธฐ ๋๋ฌธ์ธ๋ค. ๋ณดํต ์คํ์ ๋น ๋ฅด๊ณ , ํ์ ๋๋ฆฌ๋ค๊ณ ์๋ ค์ ธ ์๋ค. ๊ทธ ์ด์ ๋ ์คํ์ LIFO๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ , ํ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ ์ฐพ๊ธฐ ์ํด ์ถ๊ฐ์ ์ธ ์์ ์ด ํ์ํ๊ธฐ ๋๋ฌธ์ด๋ค. ์ค์ ๋ก๋ ์ฃผ๋ก ํผ์ฉํด์ ์ฌ์ฉํ๋๋ฐ, ์คํ์ ํ์ ํฌ์ธํฐ๋ฅผ ์ ์ฅํ๊ณ , ์ค์ ์ฐธ์กฐ๊ฐ ํ์ํ ๋ ํ์ ์ฐธ์กฐํ๋ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ๋ค.
-
์ด ๋ ํผ๋ฐ์ค๊ฐ ์๋ฏธ์๋ ์ด์ ๋ฅผ ์ ์๊ฐํด ๋ด์ผ ํ๋ค.
-
Rust๋ Stack๊ณผ Heap์ ์ฌ์ฉํ์ฌ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ด๋ฆฌํ๋ค.
-
์๋ฅผ๋ค์ด ํจ์๊ฐ ํธ์ถ ๋ ๋ ๋ง๋ค, ํจ์์ ์ง์ญ๋ณ์์ ๋งค๊ฐ๋ณ์๊ฐ ์คํ์ ์ ์ฅ๋๋ค(ํ ๋ฐ์ดํฐ ํฌํจ). ๊ทธ๋ฆฌ๊ณ ์ฌ์ฉ์ด ๋๋๋ฉด ์คํ์์ ์ ๊ฑฐ๋๋ค.
-
๊ฒฐ๋ก ์ ์ผ๋ก ์ฐ๋ฆฌ๊ฐ ๊ด๋ฆฌํด์ผํ๋ ๋ฐ์ดํฐ๋ ์ฌ์ค์ ํ์ ํ ๋น๋ ๋ฐ์ดํฐ์ด๋ค.
-
Stack์ ์ค์ฝํ ๋๋ ์ฌ์ฉ ์์ ์ ๋ฐ๋ผ ์๋์ผ๋ก ๊ด๋ฆฌ๋์ง๋ง, ํ์ ํ๋ก๊ทธ๋๋จธ๊ฐ ์ง์ ๊ด๋ฆฌํด์ผ ํ๋ค.
-
์ฑ ์์๋ Stack๊ณผ Heap์ ์๊ฐํ๋ฉด์ ํ๋ก๊ทธ๋๋ฐ ํด์ผ ํ ํ์๋ ์์ง๋ง, Ownership ์์คํ ์ด ๋ญ ์ด๋ป๊ฒ ํ๋์ง, ๊ทธ๋ฆฌ๊ณ ์ ๊ทธ๋ ๊ฒ ํ๋์ง ์ดํดํ๋๋ฐ ๋์์ด ๋๋ค๊ณ ํ๋ค.
4.1.3 Ownership Rules
๋ค์ Ownership์ ๊ท์น์ ์ดํด๋ณด๋ฉด, ๋ค์๊ณผ ๊ฐ๋ค.
- ๊ฐ๊ฐ์ ๊ฐ์ ์์ ์(owner)๊ฐ ์๋ค.
- ํ๋ฒ์ ํ๋์ ์์ ์๋ง ์กด์ฌํ ์ ์๋ค.
- ์์ ์๊ฐ ์ค์ฝํ๋ฅผ ๋ฒ์ด๋๋ฉด, ๊ฐ์ ํด์ ๋๋ค.
์ด๋ถ๋ถ์ ์ดํดํ๊ธฐ ์ํด์๋ ๋ฌ์คํธ์ ๋ณ์ ๋ฐ์ธ๋ฉ๋ฐฉ์, ์ค์ฝํ๋ฅผ ์ดํดํด์ผ ํ๋ค.
4.1.4 Variable Scope
** ๋ฌธ์์ด ๋ฆฌํฐ๋ด ์์**
fn main() { // s is not valid here, it's not yet declared
let s = "hello"; // s is valid from this point forward
} // this scope is now over, and s is no longer valid
- ์์ ์ฝ๋์ ๊ฐ์ฅ ์ค์ํ ํฌ์ธํธ
- ๋ณ์ s๋ ์ ์ธ๋ ๋ธ๋ก ๋ด์์๋ง ์ ํจํ๋ค.
- ๋ธ๋ก์ด ๋๋๋ฉด ๋ณ์ s๋ ์๋ฉธ๋๋ค.
- ์์ง๊น์ง ๋ค๋ฅธ ์ธ์ด์ ํฌ๊ฒ ๋ค๋ฅด์ง ์๋ค.
4.1.5 The String Type
String ํ์ ์์
fn main() {
let s = String::from("hello");
// do stuff with s
} // this scope is now over, and s is no longer valid
- String ํ์ ๋ ๋ณ๋ฐ ๋ค๋ฅด์ง ์์ ๊ฒ ๊ฐ์๋ฐ..?
4.1.6 Memory and Allocation
-
๋ฌธ์ ๋ฆฌํฐ๋ด์ ๊ฒฝ์ฐ, ์ปดํ์ผ ํ์์ ์ปจํ ์ธ ๋ฅผ ์ ์ ์๊ธฐ ๋๋ฌธ์, ํด๋น ์ปจํ ์ธ ๊ฐ ํ๋์ฝ๋ฉ๋์ด ๋ฐ์ด๋๋ฆฌ์ ํฌํจ๋๋ค. ๊ทธ๋์ ๋น ๋ฅด๊ณ ํจ์จ์ ์ด์ง๋ง, ๋ณ๊ฒฝ์ด ๋ถ๊ฐ๋ฅํ๋ค.
-
๋ฐ๋ฉด String ํ์ ์ ์ปดํ์ผ ํ์์ ํฌ๊ธฐ๋ฅผ ์ ์ ์๊ณ , ๋ฐํ์์ ํฌ๊ธฐ๊ฐ ๊ฒฐ์ ๋์ด ํ ๋น๋ ๊ณต๊ฐ์ ์ฐพ์ ํ์ ์ ์ฅ๋์ด์ผ ํ๋ค.
์ด ์์ ์ ๊ฐ์ฅ ์ค์ํ ํฌ์ธํธ๋ ๋ค์๊ณผ ๊ฐ๋ค.
-
๋ฐํ์์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ ์์ฒญํด์ ํ ๋นํด์ผํ๋ค.
-
๊ทธ๋ก์ธํด ์ด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํด์ ํ๊ณ ๋ฐํํดํ๋ ๋ฐฉ๋ฒ์ด ํ์ํ๋ค.
-
์ฒซ ๋ฒ์งธ๋
String::from
ํจ์๋ฅผ ํตํด ์ด๋ฃจ์ด์ก๋ค (์ฝ๋ค ์ฌ์). -
๊ทธ๋ฐ๋ฐ ๋ ๋ฒ์งธ๋ ํ๋ก๊ทธ๋๋จธ๋ค์ ์์ฃผ ์ค๋๋ ๊ณ ๋ฏผ์ค์ ํ๋์ด๋ค. (GC๊ฐ ์๋ ์ธ์ด์์๋)
- ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ๊ณ ํด์ ํ๋ ๊ฒ์ ํ๋ก๊ทธ๋๋จธ์ ๋ชซ์ด๋ค.
- ๊ทผ๋ฐ ๊ทธ๊ฒ ์ ๋๊ฒ ๋๊ณ , ์ฌ๋์ ์ค์๋ฅผ ํ๊ธฐ ๋ง๋ จ์ธ๋ฐ…
- ์ผ๋จ ํด์ ๋ฅผ ์ํ๋ฉด ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ๋ฐ์ํด์ ํ๋ก๊ทธ๋จ์ด ๋๋ ค์ง๊ณ , ๋ ์ฌํ๋ฉด ํ๋ก๊ทธ๋จ์ด ์ฃฝ์ ์ ์๋ค.
- ํด์ ๋ฅผ ๋๋ฒํ๋ฉด, ํ๋ก๊ทธ๋จ์ด ์ฃฝ์ ์ ์๋ค.
- ํด์ ๋ฅผ ๋๋ฌด ์ผ์ฐํ๋ฉด, ํ๋ก๊ทธ๋จ์ด ์ฃฝ์ ์ ์๋ค.
- ๊ฒฐ๋ก ์ ์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ ์ด๋ ต๋ค.
-
Rust๋ Ownership ๊ท์น์ ํตํด ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ค.
fn main() {
let s = String::from("hello");
// do stuff with s
} // this scope is now over, and s is no longer valid
-
์์ ์ฝ๋์์ s๋ ์ค์ฝํ๋ฅผ ๋ฒ์ด๋๋ฉด ํด์ ๋๋ค. (์ฝ๊ณ ํธ๋ฆฌํ๊ณ ์์ ํด๋ณด์ด์ง!, ์์ ํ๊ฑด ๋ง๋๋ฐ ์ฝ๊ณ ํธํ ๊น?)
-
๋ฌดํผ ์ด๊ฒ์ด Ownership์ ๊ท์น์ด๋ค.
-
์ฐธ๊ณ ๋ก ์ค์ ๊ตฌํ์
drop
์ด๋ผ๋ ํจ์๋ฅผ ํตํด ์ด๋ฃจ์ด์ง๋ค. -
์ค์ฝํ์ ๊ธฐ์ค์ด ๋๋ ๋ซํ ์ค๊ดํธ๊ฐ ์คํ๋๋ฉด, ๋ด๋ถ์ ์ผ๋ก๋
drop
ํจ์๊ฐ ํธ์ถ๋์ด ๋ฉ๋ชจ๋ฆฌ๊ฐ ํด์ ๋๋ค.
4.1.7 Ways Variables and Data Interact : Move
let x = 5;
let y = x;
- ์ฌ๊ธฐ์๋ x์ ๊ฐ์ ๋ณต์ฌํด์ y์ ๋ฃ๊ณ ์ค์ ๋ก x์ y์ธ 5๋ ์คํ์ ๊ฐ๊ฐ ํธ์๋๋ค.
let s1 = String::from("hello");
let s2 = s1;
-
์ฌ๊ธฐ๋ ๋ค๋ฅด๋ค! String์ ๋ฐ์ดํฐ๋ ์ธ ๋ถ๋ถ์ผ๋ก ๋๋์ด์ ธ ์๋ค (ํฌ์ธํฐ, ๊ธธ์ด, ์ฉ๋)
- ํฌ์ธํฐ๋ ํ์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๋ฆฌํค๋ ์ฃผ์
- ๊ธธ์ด๋ ๋ฐ์ดํฐ์ ๊ธธ์ด
- ์ฉ๋์ ํ ๋น๋ ๋ฉ๋ชจ๋ฆฌ์ ํฌ๊ธฐ
-
์ผ๋จ ์ด ๋ฐ์ดํฐ (์ฐธ์กฐ์ ๋ญ ๋์ถฉ ๋ฉํ๋ฐ์ดํฐ)๋ ์คํ์ ์ ์ฅ๋๋ค.
์ถ์ฒ : The Rust Programming Language
-
๊ทธ๋ฆฌ๊ณ s1์ s2์ ํ ๋นํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น?
-
๊ฒฐ๋ก ์ s1์ ๋ฐ์ดํฐ์ค ์คํ์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ s2๋ก ๋ณต์ฌ๋๊ณ , ํ์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ ๋ณต์ฌ๋์ง ์๋๋ค.
-
๊ทธ๋ฐ๋ฐ ๋ฌธ์ ๋ ์ฌ๊ธฐ์ ๋ฐ์ํ๋ค. s1๊ณผ s2๊ฐ ๋ชจ๋ ํ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์์ผ๋ฉด, ๋ ๋ณ์๊ฐ ์ค์ฝํ๋ฅผ ๋ฒ์ด๋๋ฉด ๋ ๋ณ์๊ฐ ๋์์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํด์ ํ๋ ค๊ณ ํ ๊ฒ์ด๋ค.
-
๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋๋ฒ ํด์ ํด…? “์ฃฝ์๊ฒ” -
๊ฐ ์๋๊ณ Rust๋ ์ด๋ฐ ์ํฉ์ ๋ฐฉ์งํ๊ธฐ ์ํด ์ฅ์น๋ฅผ ๋ง๋ จํด๋๋ค.
-
๋ด์ฉ์ ๋จผ์ ๋ณด๋ฉด
-
let s2 = s1
์ฝ๋ ์ดํ์ ์์ ์, s1์ ๋์ด์ ์ ํจํ์ง ์๋ค๊ณ ๊ฐ์ฃผํ๋ค.
let s1 = String::from("hello");
let s2 = s1;
println!("{}, world!", s1);
$ cargo run
Compiling ownership v0.1.0 (file:///projects/ownership)
error[E0382]: borrow of moved value: `s1`
--> src/main.rs:5:28
|
2 | let s1 = String::from("hello");
| -- move occurs because `s1` has type `String`, which does not implement the `Copy` trait
3 | let s2 = s1;
| -- value moved here
4 |
5 | println!("{}, world!", s1);
| ^^ value borrowed here after move
|
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider cloning the value if the performance cost is acceptable
|
3 | let s2 = s1.clone();
| ++++++++
For more information about this error, try `rustc --explain E0382`.
error: could not compile `ownership` due to previous error
-
์ค์ ๋ก ์ด๋ฐ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
-
์์ ๋ณต์ฌ ๋๋ ์์ ๋ผ๊ณ ์ ์ด ๊ทผ์ง๊ทผ์งํ์ จ๋๋ถ๋ค์ ๊ณ ๋ คํด์ผ ํ ๊ฒ ํ๋ ๋ ๋์ ์์ด๋ค.
-
Rust๋ ์์ ๋ณต์ฌ๋ฅผ ํ์ง ์๊ณ , move๋ผ๋ ๊ฐ๋ ์ ์ฌ์ฉํ๋ค.
์ถ์ฒ : The Rust Programming Language
-
๊ฒฐ๋ก ์ ์ผ๋ก ์ค์ฝํ๋ฅผ ๋๊ฐ๋๋ง๋ค ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํด์ ํ๋ฉด ๋๋๋ฐ ์ ๊ทธ๋ ๊ฒ ์ํ์ง? ์ ๊ฐ์ ์๊ฐ์๋ ๋ค์๊ณผ ๊ฐ์ ์ด์ ๊ฐ ์์๊ณ (์ค๋ณต ํด์ ) ๋ฌ์คํธ๋ ์ด๋ฌํ ๋ถ๋ถ๋ค์ ๋ํ ๊ท์น์ ์ง์ ํ๋ฉฐ ํด๊ฒฐํ๊ณ ์๋ ๊ฒ์ด๋ค.
-
์ฐธ๊ณ ๋ก ๊น์ ๋ณต์ฌ๋ฅผ ํ๊ณ ์ถ๋ค๋ฉด
clone
ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
let s1 = String::from("hello");
let s2 = s1.clone();
println!("{}, world!", s1);
- ์ด๋ ๊ฒ ํ๋ฉด s1๊ณผ s2๋ ์๋ก ๋ค๋ฅธ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ๋๋ค.
4.1.8 Copy Trait
-
์์์ ๋ถ๋ฅํ Stack only ํ์ ๋ค์ ๊ตณ์ด move๋ฅผ ํ์ง ์์๋ ๋๋ค.
-
์ด๋ฐ ํ์ ๋ค์ Copy ํธ๋ ์ดํธ๋ฅผ ๊ตฌํํ๊ณ ์๋ค.
-
Copy ํธ๋ ์ดํธ๋ ๋ค์๊ณผ ๊ฐ์ ํน์ง์ ๊ฐ์ง๋ค.
-
์คํ์ ์ ์ฅ๋๋ ํ์ ๋ค์ Copy ํธ๋ ์ดํธ๋ฅผ ๊ตฌํํ๊ณ ์๋ค.
-
Copy ํธ๋ ์ดํธ๋ฅผ ๊ตฌํํ๊ณ ์๋ ํ์ ๋ค์ move ๋์ ๋ณต์ฌ๊ฐ ์ด๋ฃจ์ด์ง๋ค.
-
Copy ํธ๋ ์ดํธ๋ฅผ ๊ตฌํํ๊ณ ์๋ ํ์ ๋ค์ ์ค์ฝํ๋ฅผ ๋ฒ์ด๋๋ ๋ฉ๋ชจ๋ฆฌ๊ฐ ํด์ ๋์ง ์๋๋ค.
-
-
Copy ํธ๋ ์ดํธ๋ฅผ ๊ตฌํํ๊ณ ์๋ ํ์ ๋ค์ ๋ค์๊ณผ ๊ฐ๋ค.
- i32 - bool - f64 - char - Tuple (๋จ, ๋ชจ๋ ์์๊ฐ Copy ํธ๋ ์ดํธ๋ฅผ ๊ตฌํํ๊ณ ์์ด์ผ ํ๋ค.)
-
์ด์ธ์๋ drop trait๋ฅผ ๊ตฌํํ๊ณ ์์ด Copy ํธ๋ ์ดํธ๋ฅผ ๊ตฌํํ ์ ์๋ค.
4.1.9 Ownership and Functions
-
ํจ์์ ์ธ์๋ก ๊ฐ์ ๋๊ธฐ๋ ๊ฒ์ ๋ณ์๋ฅผ ํ ๋นํ๋ ๊ฒ๊ณผ ์๋ฏธ๋ก ์ ์ผ๋ก ๋น์ทํ๋ค.
-
ํจ์์ ์ธ์๋ก ๊ฐ์ ๋๊ธฐ๋ฉด, ํด๋น ๊ฐ์ ํจ์์ ์ค์ฝํ๋ก ์ด๋ํ๋ค.
fn main() {
let s = String::from("hello"); // s comes into scope
takes_ownership(s); // s's value moves into the function...
// ... and so is no longer valid here
let x = 5; // x comes into scope
makes_copy(x); // x would move into the function,
// but i32 is Copy, so it's okay to still
// use x afterward
} // Here, x goes out of scope, then s. But because s's value was moved, nothing
// special happens.
fn takes_ownership(some_string: String) { // some_string comes into scope
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) { // some_integer comes into scope
println!("{}", some_integer);
} // Here, some_integer goes out of scope. Nothing special happens.
- ํจ์์ ๋ฐํ๊ฐ ์ญ์ ๋ง์ฐฌ๊ฐ์ง๋ก move๊ฐ ์ด๋ฃจ์ด์ง๋ค.
fn main() {
let s1 = gives_ownership(); // gives_ownership moves its return
// value into s1
let s2 = String::from("hello"); // s2 comes into scope
let s3 = takes_and_gives_back(s2); // s2 is moved into
// takes_and_gives_back, which also
// moves its return value into s3
} // Here, s3 goes out of scope and is dropped. s2 was moved, so nothing
// happens. s1 goes out of scope and is dropped.
fn gives_ownership() -> String { // gives_ownership will move its
// return value into the function
// that calls it
let some_string = String::from("yours"); // some_string comes into scope
some_string // some_string is returned and
// moves out to the calling
// function
}
// This function takes a String and returns one
fn takes_and_gives_back(a_string: String) -> String { // a_string comes into
// scope
a_string // a_string is returned and moves out to the calling function
}
-
๋ฉ๋์ด ์๊ฐ๋ ์์ ๋ ์๋ ๊ฒ ๊ฐ๋ค.
-
๋ค๋ง ๋ชจ๋ ํจ์๊ฐ ์์ ๊ถ์ ๊ฐ์ ธ๊ฐ๋ค๊ฐ ๋ฐํํ๋๊ฒ์ ์ง๋ฃจํ๊ธฐ ๋๋ฌธ์ ๋ฌ์คํธ๋ ์ฐธ์กฐ๋ฅผ ์ฌ์ฉํ๋ค.
4.2 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 is a reference to a String
s.len()
}
- ๋ฌ์คํธ์์ ์ฐธ์กฐ๋ ๋ณ์๋ฅผ ๋น๋ ค์ค๋ ๊ฒ์ด๋ค.
-
์ฐธ๊ณ ๋ก reference์ ๋ฐ๋๋ dereference์ด๋ฉฐ
*
์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ๋ค. -
์ฐธ์กฐ๋ฅผ ์ฌ์ฉํ๋ฉด ์์ ๊ถ์ ๋๊ธฐ์ง ์์ผ๋ฏ๋ก,
drop
ํจ์๊ฐ ํธ์ถ๋์ง ์๋๋ค. -
์ฐธ์กฐ๋ ๊ธฐ๋ณธ์ ์ผ๋ก immutableํ๋ค.
fn main() {
let s = String::from("hello");
change(&s);
}
fn change(some_string: &String) {
some_string.push_str(", world");
}
- ์์ ์ฝ๋๋ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
$ cargo run
Compiling ownership v0.1.0 (file:///projects/ownership)
error[E0596]: cannot borrow `*some_string` as mutable, as it is behind a `&` reference
--> src/main.rs:8:5
|
7 | fn change(some_string: &String) {
| ------- help: consider changing this to be a mutable reference: `&mut String`
8 | some_string.push_str(", world");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `some_string` is a `&` reference, so the data it refers to cannot be borrowed as mutable
For more information about this error, try `rustc --explain E0596`.
error: could not compile `ownership` due to previous error
- ์ฐธ์กฐ๋ฅผ mutable๋ก ์ฌ์ฉํ๋ ค๋ฉด
&mut
์ ์ฌ์ฉํด์ผ ํ๋ค.
fn main() {
let mut s = String::from("hello");
change(&mut s);
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}
- ์ฐธ์กฐ๋ฅผ ์ฌ์ฉํ๋ฉด ์์ ๊ถ์ ๋๊ธฐ์ง ์์ผ๋ฏ๋ก, ์ฌ๋ฌ ์ฐธ์กฐ๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
fn main() {
let mut s = String::
from("hello");
let r1 = &mut s;
let r2 = &mut s;
println!("{}, {}", r1, r2);
}
$ cargo run
Compiling ownership v0.1.0 (file:///projects/ownership)
error[E0499]: cannot borrow `s` as mutable more than once at a time
--> src/main.rs:5:17
|
4 | let r1 = &mut s;
5 | let r2 = &mut s;
| ^^^^ mutable borrow starts here in previous iteration of loop
6 |
7 | println!("{}, {}", r1, r2);
| -- borrow later used here
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: aborting due to previous error
For more information about this error, try `rustc --explain E0499`.
error: could not compile `ownership` due to previous error
-
์ค์ ์ฝ๋๋ฅผ ์์ฑํ๋๋ฐ ๊ฐ์ฅ ํ๋ค๊ฒ ๋๊ปด์ง๋ ์ ์ฝ์ฌํญ ์ค ํ๋์ด๋ค.
-
๋ฌ์คํธ๋ ์ด๋ฌํ ์ ์ฝ์ฌํญ์ ํตํด ๋ฉ๋ชจ๋ฆฌ ์์ ์ฑ์ ๋ณด์ฅํ๋ค.
-
์ ํํ๋ ๋ฌ์คํธ๋ ๋ฐ์ดํฐ ๋ ์ด์ค๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ์ด๋ฌํ ์ ์ฝ์ฌํญ์ ๋๊ณ ์๋ค.
-
๋ฐ์ดํฐ ๋ ์ด์ค๋ ๋๊ฐ ์ด์์ ์ค๋ ๋๊ฐ ๋์์ ๊ฐ์ ๋ฐ์ดํฐ์ ์ ๊ทผํ ๋ ๋ฐ์ํ๋ ๋ฌธ์ ์ด๋ค.
- ๋์์ ๊ฐ์ ๋ฐ์ดํฐ์ ์ ๊ทผํ๋ฉด์, ์ ์ด๋ ํ๋์ ์ ๊ทผ์ด ์ฐ๊ธฐ์ผ ๋, ๋์์ฑ ๋ก์ง์ด ์๋ ๊ฒฝ์ฐ์ ๋ฐ์ํ๋ค.
-
๋ฌ์คํธ๋ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ์ปดํ์ผ ํ์์ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ๋ฐฉ์งํ๋ค.
fn main() {
let mut s = String::("hello");
{
let r1 = &mut s;
} // r1 goes out of scope here, so we can make a new reference with no problems.
let r2 = &mut s;
-
๋ค์์ ์ฐธ์กฐ๊ฐ ํ์ ํ ๋, ์์ ๊ฐ์ด ๋ธ๋ก์ ์ฌ์ฉํ์ฌ ์ค์ฝํ๋ฅผ ๋๋์ด ์ฌ์ฉํ๋ฉด ๋๋ค.
-
์ฐธ์กฐ์ ๋ฒ์๋ฅผ ์ ํํจ์ผ๋ก์จ, ๋ฐ์ดํฐ ๋ ์ด์ค๋ฅผ ๋ฐฉ์งํ ์ ์๋ค.
-
๋ ํ๋์ ์ ์ฝ์ฌํญ์ ๋ถ๋ณ ์ฐธ์กฐ์ ๊ฐ๋ณ ์ฐธ์กฐ๋ฅผ ๋์์ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์ด๋ค.
fn main() {
let mut s = String::from("hello");
let r1 = &s;
let r2 = &s;
let r3 = &mut s; // error
}
-
๋ถ๋ณ ์ฐธ์กฐ๊ฐ์ด ์๋ ๋์์๋ ๊ฐ๋ณ ์ฐธ์กฐ๋ก ์ธํด์ ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋๋๊ฒ์ ์ํ์ง ์๊ธฐ ๋๋ฌธ์ ๋ง์๋ ๊ฒ์ด๋ค.
-
์ถ๊ฐ์ ์ผ๋ก ๋ฌ์คํธ๋ ์ปดํ์ผ ์์ ์ ๋ถ๋ณ ์ฐธ์กฐ์ ๋ง์ง๋ง ์ฌ์ฉ ์์น ์ดํ์๋ ๊ฐ๋ณ ์ฐธ์กฐ๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ํด์ค๋ค.
fn main() {
let mut s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{} and {}", r1, r2);
// r1 and r2 are no longer used after this point
let r3 = &mut s;
}
4.2.1 Dangling References
-
Dangling References๋ ์ฐธ์กฐ๊ฐ ๊ฐ๋ฆฌํค๋ ๋ฉ๋ชจ๋ฆฌ๊ฐ ํด์ ๋ ๊ฒฝ์ฐ๋ฅผ ๋งํ๋ค.
- ๋ฉ๋ชจ๋ฆฌ ํด์ ํ์๋ ์ฐธ์กฐ๊ฐ ์กด์ฌํ๋ ๊ฒฝ์ฐ,
- ๋ฒ์ ๋ฐ ์ฐธ์กฐ๊ฐ ์ผ์ด๋๋ ๊ฒฝ์ฐ,
- ๋ณต์ฌ๋ ํฌ์ธํฐ๊ฐ ์ผ์ผํค๋ ๊ฒฝ์ฐ ๋ฑ์ด ์๋ค.
-
๋ฌ์คํธ๋ ์ฐธ์กฐ๊ฐ ์ ํจํ ๋์์๋ ๋ฐ๋์ ๋ฐ์ดํฐ๊ฐ ์ค์ฝํ ๋ด์ ์๋๋ก ๋ณด์ฅํ๋ค.
-
์ฆ, ๋ฐ์ดํฐ๊ฐ ์ฐธ์กฐ๋ณด๋ค ๋จผ์ ์ค์ฝํ ๋ฐ์ผ๋ก ๋ฒ์ด๋์๋ ์ ๋๋ฉฐ, ์ด๋ฅผ ํตํด ๋๊ธ๋ง ์ฐธ์กฐ๊ฐ ์์ฑ๋๋ ๊ฒ์ ์ปดํ์ผ ์์ ์ ๋ฐฉ์งํ๋ค.
-
์๋ฅผ๋ค์ด ํจ์๊ฐ ๋ก์ปฌ ๋ณ์์ ์ฐธ์กฐ๋ฅผ ๋ฐํํ๋ ๊ฒฝ์ฐ, ๋ฌ์คํธ๋ ์ปดํ์ผ ์๋ฌ๋ฅผ ๋ฐ์์ํจ๋ค.
fn main() {
let reference_to_nothing = dangle();
}
fn dangle() -> &String {
let s = String::from("hello");
&s
}
4.3 The Slice Type
-
์ฌ๋ผ์ด๋๋ ์ฐธ์กฐ์ ์ผ์ข ์ผ๋ก, ์ค๋์ฝ์ ๊ฐ์ง์ง ์๋๋ค.
-
์์ : ๋ฌธ์์ด์์ ์ฒซ ๋จ์ด๋ฅผ ์ฐพ๋ ํจ์ ๋ง๋ค์ด๋ณด๊ธฐ (๊ณต๋ฐฑ์ ๊ธฐ์ค์ผ๋ก)
fn first_word(s: &String) -> ?
- ์ด ํจ์๋ ๋ฌธ์์ด์ ์ฐธ์กฐ๋ฅผ ๋ฐ๋๋ฐ, ๋ฌด์์ ๋ฐํํด์ผ ํ ๊น?
fn first_word(s: &String) -> usize {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return i;
}
}
s.len()
}
let bytes = s.as_bytes(); // as_bytes() ๋ฉ์๋๋ ๋ฌธ์์ด์ ๋ฐ์ดํธ ๋ฐฐ์ด๋ก ๋ณํํ๋ค.
for (i, &item) in bytes.iter().enumerate() // iter() ๋ฉ์๋๋ ์ปฌ๋ ์
์ ๋ฐ๋ณตํ๋ ๋ฐ๋ณต์๋ฅผ ์์ฑํ๋ค, enumerate() ๋ฉ์๋๋ ๋ฐ๋ณต์๋ฅผ ํํ๋ก ๋ณํํ๋ค.
- ๋ฌธ์์ด์ ์ธ๋ฑ์ค๋ฅผ ๋ฐํํ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ๋ค,
fn main() {
let mut s = String::from("hello world");
let word = first_word(&s); // word will get the value 5
s.clear(); // this empties the String, making it equal to ""
// word still has the value 5 here, but there's no more string that
// we could meaningfully use the value 5 with. word is now totally invalid!
}
4.3.1 String Slices
- ์ฌ๋ผ์ด์ค๋ ๋ฌธ์์ด์ ์ผ๋ถ๋ถ์ ์ฐธ์กฐํ๋ ๋ฐฉ๋ฒ์ด๊ณ ์ด๋ ๊ฒ ์๊ฒผ๋ค.
let s = String::from("hello world");
let hello = &s[0..5];
let world = &s[6..11];
Rather than a reference to the entire String, hello is a reference to a portion of the String, specified in the extra [0..5] bit. We create slices using a range within brackets by specifying [starting_index..ending_index], where starting_index is the first position in the slice and ending_index is one more than the last position in the slice. Internally, the slice data structure stores the starting position and the length of the slice, which corresponds to ending_index minus starting_index. So, in the case of let world = &s[6..11];, world would be a slice that contains a pointer to the byte at index 6 of s with a length value of 5.
let s = String::from("hello");
let slice = &s[0..2];
let slice = &s[..2];
let len = s.len();
let slice = &s[3..len];
let slice = &s[3..];
let slice = &s[0..len];
let slice = &s[..];
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[..]
}
-
๋๊ฐ์ด ๊ฐ๋ ์ ์ผ๋ก๋ ์ธ๋ฑ์ค๋ฅผ ํตํด ๋ฌธ์์ด์ ์ฐพ๋ ๋ฐฉ์์ด์ง๋ง, ์ฐธ์กฐ๋ฅผ ์ฎ์ด๋๋ฉด ํจ์ฌ ๋ ์์ ํ๊ฒ ์ฌ์ฉ ํ ์ ์๋ค.
-
์คํธ๋ง์ด ์ ํจํ ๋์์ ์ฌ๋ผ์ด์ค๋ ์ ํจํ๋ค.
fn main() {
let mut s = String::from("hello world");
let word = first_word(&s);
s.clear(); // error!
println!("the first word is: {}", word);
}
$ cargo run
Compiling ownership v0.1.0 (file:///projects/ownership)
error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable
--> src/main.rs:18:5
|
16 | let word = first_word(&s);
| -- immutable borrow occurs here
17 |
18 | s.clear(); // error!
| ^^^^^^^^^ mutable borrow occurs here
19 |
20 | println!("the first word is: {}", word);
| ---- immutable borrow later used here
For more information about this error, try `rustc --explain E0502`.
error: could not compile `ownership` due to previous error
-
String์ ๋ด์ฉ์ ์ง์ฐ๊ธฐ ์ํด์๋ ํด๋น String์ ๋ํ ๊ฐ๋ณ ์ฐธ์กฐ๊ฐ ํ์ํ๋ฐ, ๋ง์ฝ ์ด๋ฏธ ๋ถ๋ณ ์ฐธ์กฐ๊ฐ ์กด์ฌํ๋ค๋ฉด
-
clear ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ String์ ๋ด์ฉ์ ๋ณ๊ฒฝํ๋ ค๊ณ ํ ๋ ์ปดํ์ผ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
-
์ด๋ println! ๋งคํฌ๋ก๊ฐ word์์ ๋ถ๋ณ ์ฐธ์กฐ๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํ๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ๋ค.
-
๋ฐ๋ผ์, clear ํจ์๊ฐ ๊ฐ๋ณ ์ฐธ์กฐ๋ฅผ ์๊ตฌํ๋ ๋์ word์ ๋ถ๋ณ ์ฐธ์กฐ๊ฐ ์ฌ์ ํ ํ์ฑํ๋์ด ์์ด์ผ ํ๋ค.
-
๋ฌ์คํธ๋ ๊ฐ๋ณ ์ฐธ์กฐ์ ๋ถ๋ณ ์ฐธ์กฐ๊ฐ ๋์์ ์กด์ฌํ๋ ๊ฒ์ ํ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์ ์ปดํ์ผ์ด ์คํจํ๋ค.
-
๊ฒฐ๋ก ์ ์ผ๋ก String Literal์ ๋ฐ์ด๋๋ฆฌ๋ฅผ ์ฐธ์กฐํ๋ ๊ฒ์ด๋ค.
์ ์ฝ๋์์ s์ ํ์ ์ &str์ ๋๋ค. ์ด๋ ํน์ ์ด์ง ํ์ผ ๋ด์ ์์น๋ฅผ ๊ฐ๋ฆฌํค๋ ์ฌ๋ผ์ด์ค๋ก, ๋ฌธ์์ด ๋ฆฌํฐ๋ด์ด ์ด๋ป๊ฒ ์ฒ๋ฆฌ๋๋์ง๋ฅผ ๋ช ํํ ์ดํดํ ์ ์๊ฒ ํด์ค๋๋ค. ๋ฌธ์์ด ๋ฆฌํฐ๋ด์ด ๋ถ๋ณ์ธ ์ด์ ๋ ์ฌ๊ธฐ์ ์์ต๋๋ค &str์ ๋ถ๋ณ ์ฐธ์กฐ์ด๊ธฐ ๋๋ฌธ์ ๋๋ค.๋ฐ๋ผ์, ๋ฌธ์์ด ๋ฆฌํฐ๋ด์ ํ๋ก๊ทธ๋จ์ ์ด์ง ํ์ผ ๋ด์ ์ง์ ์ ์ฅ๋๋ฉฐ, ์ด๋ฅผ ํตํด ์์ฑ๋ &str ํ์ ์ ๋ณ์๋ ์ด์ง ํ์ผ ๋ด ํด๋น ๋ฌธ์์ด์ ์์น๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ถ๋ณ์ ์ฌ๋ผ์ด์ค๊ฐ ๋ฉ๋๋ค. ์ด๋ฌํ ํน์ฑ์ ๋ฌธ์์ด ๋ฆฌํฐ๋ด์ด ์ ๋ณ๊ฒฝํ ์ ์๋์ง(immutable)๋ฅผ ์ค๋ช ํด ์ค๋๋ค.
let s = "Hello, world!";
- ์ฐธ๊ณ ๋ก ๊ฒฝํ ๋ง์ ๊ฐ๋ฐ์๋ค์ ๋ค์๊ณผ ๊ฐ์ด ์๊ทธ๋์ฒ๋ฅผ ์ ์ฐํ๊ฒ ๋ง๋ค์ด์ ์ฌ์ฉํ๋ค๊ณ ํ๋ค.
fn first_word(s: &str) -> &str
-
์์ฒ๋ผ s ๋งค๊ฐ๋ณ์์ ํ์ ์ผ๋ก ๋ฌธ์์ด ์ฌ๋ผ์ด์ค๋ฅผ ์ฌ์ฉํ๊ฒ ๋ง๋ ๋ค.
-
์ด๋ฅผ ํตํด ๋ฌธ์์ด ์ฌ๋ผ์ด์ค๋ฅผ ์ง์ ์ ๋ฌํ ์ ์๊ณ , String์ด ์์ ๊ฒฝ์ฐ String์ ์ฌ๋ผ์ด์ค๋ String์ ๋ํ ์ฐธ์กฐ๋ฅผ ์ ๋ฌํ ์ ์๊ฒ ๋๋ค.
-
์ด๋ฌํ ์ ์ฐ์ฑ์ ์ญ์ฐธ์กฐ ๊ฐ์ ๋ณํ(deref coercions)์ด๋ผ๋ ๊ธฐ๋ฅ์ ํ์ฉํ๋ ๊ฒ์ผ๋ก
๋์ค์…
fn main() {
let my_string = String::from("hello world");
// `first_word` works on slices of `String`s, whether partial or whole
let word = first_word(&my_string[0..6]);
let word = first_word(&my_string[..]);
// `first_word` also works on references to `String`s, which are equivalent
// to whole slices of `String`s
let word = first_word(&my_string);
let my_string_literal = "hello world";
// `first_word` works on slices of string literals, whether partial or whole
let word = first_word(&my_string_literal[0..6]);
let word = first_word(&my_string_literal[..]);
// Because string literals *are* string slices already,
// this works too, without the slice syntax!
let word = first_word(my_string_literal);
}