Rust(r26)

해당 리비전 수정 시각: ()
[주의!] 문서의 이전 버전(에 수정)을 보고 있습니다. 최신 버전으로 이동
fn main() {
  println!("hello, world!");
}
파일:Crates.io logo.pngcrates.io[1] 파일:Docs.rs logo.pngdocs.rs파일:GitHub 아이콘 light.svg파일:GitHub 아이콘 dark.svggithub
메모리 안전성을 중요시 여기는 언어이다. 모질라 제단에서 관리하다가 러스트 제단으로 넘어왔다.

원래는 모질라 직원의 개인 프로젝트였으나, Servo를 만들게 되면서 새 언어를 찾다가 Rust를 발견하고 밀어주게 되었다.

페리스라는 마스코트가 있다.

1. 특징 [편집]

1.1. 소유권 [편집]

러스트를 배울 때 나오면 가장 때려치고 싶게 만드는 원흉. 메모리를 바로바로 해지하는 언어 특성상 소유권은 메우 중요한 계념이다.

1.1.1. 함수에 넘기기 [편집]

또한 어떤 함수에 인자로 값을 넘기면 그 값의 소유권은 만료된다.
fn main () {
  let a:u8 = 0;
  take_ownership(a);
  println("{a}");
}
fn take_ownership (a:u8) {
}
이를 실행해도 컴파일 에러가 나는데 a를 함수에 넘긴 다음에 사용하려 하였기 때문이다. 이럴 때는 to_owned(), clone()등을 써서 값을 복사함으로서 해결할 수 있지만[2] 더 좋은 방법이 있다.

또한 Copy trait이 구현되어있다면, 함수에 넣을 시에 자동으로 값이 복사되어서 딱히 값을 복사하거나 할 필요가 없다.[3]

1.1.2. 참조자 [편집]

어떤 함수의 값을 넘길 때
fn main() {
  let a:u8 = 0
  borrow_me(&a);
  println("{a}")
}
fn borrow_me (a:&u8) {
}
이렇게 함수에 넘길 때 참조자(&)를 사용하면 소유권을 유지할 수 있다.

1.2. lifetime [편집]

러스트의 난이도를 높히는 주범 포인터가 혜지된 메모리를 가리키는 것을 방지하려 만들었다. 러스트라는 언어 자체가 null pointer exception[4]을 피하려고 설계되었기 때문이다.

1.2.1. 스코프 [편집]

가장 중요한 계념 중 하나는 스코프[5] 밖을 벗어나면 스코프 안에서 정의된 변수는 사용할 수 없다인데 예를들어
fn main () {
  {
    let a:u8 = 0;
  }
  println!("{a}");
}
를 실행하면 컴파일 에러가 난다.[6] 왜냐하면 스코프 안에서 선언 된 a를 수명이 끝난 스코프 밖에서 값을 조회하였기 때문이다.

1.2.2. 제내릭 라이프타임 [편집]

1.2.2.1. 참조 둘 중 하나를 반환하는 함수 [편집]
지옥의 시작
fn longest<'a> (s1:&`a str,s2:&`a str) -> &`a str {
    if s1.len() > s2.len() {
        s1
    } else {
        s2
    }
}

함수 뒤에 꺽쇠 괄호가 있는 것을 볼 수 있는데 이렇게 생각하면 된다.
fn any<T> (input:T) {
    //input은 어떤 타입이든 될 수 있음
}

위의 예시처럼 `a는 어느 라이프타임이든 될 수 있다는 것이다.

다시 longest로 돌아가보자. 아하 longest 함수의 s1과 s2는 공통된 생명 주기를 가져야하고 리턴값의 생명주기도 같아야하구나.라는 사실을 알수 있다. 왜냐?
fn main () {
    let s1 = String::new();
    let result;
    {
        let s2 = String::new();
        result = longest(&s1, &s2);
    }
    println!("{result}");
}

만약 위 코드에서 함수가 s2를 리턴한다면 어떤일이 벌어질지 생각해보자.

result를 조회 할 때 s2의 원본을 조회해야하는데 그게 스코프를 나가버려서 사라져버렸다. 따라서 null pointer가 된다.

그러면 의문이 들 것이다. "아니 그러면 런타임 에러를 발생시키면 되잖아." 그런데 러스트는 그걸 하지 말라 만든 언어다. 언어 설계에 모순이 생긴다.

"아니 그러면 애초부터 result를 longest의 리턴으로 못넣게 하면 되잖아." 그게 수명주기 명시다. 지금 longest의 리턴값은 s2의 수명주기와 같다.[7]

"그럼 인풋중 수명이 더 짧은 것을 리턴의 수명으로 정하면 되잖아?" 할 수 있는데 안한다(...) 아니 왜요?

2. 그 외 [편집]

  • 컴파일 언어이다.
  • 컴파일 시간에 대부분의 런타임 에러를 잡아낸다.

3. 함께보기 [편집]

[1] rust계의 npm[2] clone은 벡터, String등 실제 값을 가리키는 포인터를 복사하는 반면(shallow copy), toowned는 그 메모리 내용까지 복사한다.(deep copy)[3] 그래서 사실 위의 예제를 실행해도 에러는 안난다. u8 type이 Copy trait을 구현하였기 때문[4] dangling pointer라고 많이 불리는듯[5] {랑 }사이[6] 런타임 에러가 아니다![7] `a로 수명주기를 명시한것 중이서 s2가 수명이 가장 짧기 때문

라이선스를 별도로 명시하지 않은 문서는 CC BY-SA 4.0에 따라 이용할 수 있습니다.
자세한 내용은 다올위키 라이선스 정책을 확인하시기 바랍니다.

기여하신 문서의 저작권은 각 기여자에게 있으며, 각 기여자는 기여하신 부분의 저작권을 갖습니다.

오픈 소스가 아닌 다올위키의 고유한 디자인을 무단으로 도용하는 것과, 운영 문서를 포함한 모든 문서를 라이선스를 지키지 않고 무단으로 가져가는 행동은 저작권 위반이며 법적 책임을 물 수 있습니다.