r2
| 1 | {{{#!syntax rust |
|---|
| 2 | fn main() { |
|---|
| 3 | println!("hello, world!"); |
|---|
| 4 | } |
|---|
| 5 | }}}[[https://crates.io|[[파일:홈페이지 아이콘.svg|width=25px]]]],,crates.io,,[* rust계의 npm] [[https://github.com/rust-lang/rust|[[파일:GitHub 아이콘 light.svg|width=25px&theme=light]]]][[https://github.com/rust-lang/rust|[[파일:GitHub 아이콘 dark.svg|width=25px&theme=dark]]]],,github,, |
|---|
| 6 | 메모리 안전성을 중요시 여기는 언어이다. 모질라 제단에서 관리하다가 러스트 제단으로 넘어왔다. |
|---|
| 7 | |
|---|
| 8 | 페리스라는 마스코트가 있다. |
|---|
| 9 | == 특징 == |
|---|
r3
| 10 | === 소유권 === |
|---|
| 11 | 러스트를 배울 때 나오면 가장 때려치고 싶게 만드는 원흉. 메모리를 바로바로 혜지하는 언어 특성상 소유권은 메우 중요한 계념이다. |
|---|
| 12 | ==== 스코프 ==== |
|---|
| 13 | 가장 중요한 계념 중 하나는 스코프[* {랑 }사이] 밖을 벗어나면 스코프 안에서 정의된 변수는 사용할 수 없다인데 예를들어{{{#!syntax rust |
|---|
| 14 | fn main () { |
|---|
| 15 | { |
|---|
| 16 | let a = "앙되 내 수명은 여기까지야"; |
|---|
| 17 | } |
|---|
| 18 | println!("{a}"); |
|---|
| 19 | } |
|---|
r5
| 20 | }}}를 실행하면 컴파일 에러가 난다.[* 런타임 에러가 아니다!] 왜냐하면 스코프 안에서 선언 된 a를 밖에서 값을 조회하였기 때문이다. |
|---|
r3
| 21 | ==== 함수에 넘기기 ==== |
|---|
r4
| 22 | 또한 어떤 함수에 인자로 값을 넘기면 그 값의 소유권은 만료된다.{{{#!syntax rust |
|---|
| 23 | fn main () { |
|---|
| 24 | let a = "앙되 내가 함수의 인자로 들어감으로서 이 함수로 돌아오지 못하게 되었어."; |
|---|
r3
| 25 | 소유권은내것(a); |
|---|
r4
| 26 | println("{a}"); |
|---|
r3
| 27 | } |
|---|
| 28 | fn 소유권은내것 (a:&str) { |
|---|
| 29 | } |
|---|
r5
| 30 | }}}이를 실행해도 컴파일 에러가 나는데 a를 함수에 넘긴 다음에 사용하려 하였기 때문이다. 이럴 때는 to_owned(), clone()등을 써서 값을 복사함으로서 해결할 수 있지만[* clone은 벡터, String등 실제 값을 가리키는 포인터를 복사하는 반면(shallow copy), toowned는 그 메모리 내용까지 복사한다.(deep copy)] 더 좋은 방법이 있다. |
|---|
r3
| 31 | ==== &참조자 ==== |
|---|
| 32 | 어떤 함수의 값을 넘길 때 |
|---|
r4
| 33 | {{{#!syntax rust |
|---|
r3
| 34 | fn main() { |
|---|
| 35 | let a = "참조자를 사용함으로서 나는 여전히 살아있다고." |
|---|
| 36 | 소유권좀_빌려주세요(&a); |
|---|
| 37 | println("{a}") |
|---|
| 38 | } |
|---|
| 39 | fn 소유권은내것 (a:&&str) { |
|---|
| 40 | } |
|---|
r5
| 41 | }}}이렇게 함수에 넘길 때 참조자를 사용하면 소유권을 유지할 수 있다. [* 사실 &str은 이미 참조자가 붙어있어서 상관없긴 하지만 예시에 String::from을 넣으면 너무 길어서 간단하게 하려고 한 것이다.~~???:선생님 예시가 이상해요~~] |
|---|
| 42 | ==== lifetime ==== |
|---|
| 43 | '''러스트의 난이도를 높히는 주범''' 포인터가 혜지된 메모리를 가리키는 것을 방지하려 만들었다. 예를들어서{{{#!syntax rust |
|---|
| 44 | fn main () { |
|---|
| 45 | let result = 로직(); |
|---|
| 46 | } |
|---|
| 47 | fn 로직() -> &str { |
|---|
| 48 | let a = "cc"; |
|---|
| 49 | return str; |
|---|
| 50 | } |
|---|
| 51 | }}} 위 코드에서는 로직 함수는 스코프 내에서 a를 정의하고 반환하는 과정속, return을 통해 함수의 스코프를 벗어나게 된다. 이때, a의 메모리가 혜지되면서 result의 값은 접근불가하게 된다. [* 러스트의 참조 타입은 모두 원본값을 가리키는 포인터인데, 원본의 메모리가 혜지됨 -> 이러한 포인터에 접근하는 것은 memory-unsafe한 접근으로, 언어가 허용하지 않음] |
|---|
| 52 | |
|---|
| 53 | 이러한 문제를 해결하기 위해 반환값의 수명을 늘려야 한다. |
|---|
| 54 | {{{#!syntax rust |
|---|
| 55 | fn main () { |
|---|
| 56 | let result = 로직(); |
|---|
| 57 | } |
|---|
| 58 | fn 로직<'a>() -> &'a str { |
|---|
| 59 | let 문자열 = "cc"; //문자열의 타입은 자동추론에 의해 &str이 아니라 &'a str이라는 것을 기억하자. |
|---|
| 60 | return str; |
|---|
| 61 | } |
|---|
| 62 | }}} |
|---|
| 63 | 이렇게 수정을 하면 result가 만료될 때 까지 원본 값인 문자열은 만료가 되지 않는다! |
|---|
| 64 | |
|---|
| 65 | 참고로 'a대신 'b 'c든 다 사용 가능하다. 'static은 절대로 만료되지 않게 만들어 버린다. ~~메모리 누수일세~~ |
|---|
r3
| 66 | == 그 외 == |
|---|
r2
| 67 | * 컴파일 언어이다. |
|---|
| 68 | * 컴파일 시간에 대부분의 런타임 에러를 잡아낸다. |
|---|