[6] 표준 라이브러리

표준 라이브러리

  • 옵션 및 결과: 값이 존재하거나 존재하지 않는 경우 및 오류 처리에 사용됩니다.
  • 문자열: 문자열 데이터를 소유할 때 사용되는 기본 문자열 유형입니다.
  • Vec: 표준 가변 크기 벡터 유형.
  • HashMap: 해시 알고리즘을 별도로 지정할 수 있는 해시 맵 유형입니다.
  • 상자: 힙 데이터에 대한 소유 포인터입니다.
  • Rc: 힙에 할당된 데이터에 대한 참조 횟수 공유 포인터입니다.

옵션과 결과

결과 유형

pub enum Result<T, E> {
    Ok(T),
    Err(E),
}

결과 유형은 열거 유형이며 열거라고도 합니다.
결과의 변형은 다음과 같습니다.
Ok그리고 Err오전. 확인은 프로세스가 성공했고 성공적으로 결과를 생성했음을 나타냅니다.
Err에는 실패한 처리와 그 이유에 대한 정보가 포함되어 있습니다.

결과에는 다른 유형과 같은 메소드가 있습니다.
expectResult 인스턴스가 Err이면 메서드는 프로그램을 중지하고 예상 인수로 전달된 메시지를 인쇄합니다.

결과가 OK이면 Expect는 OK 결과를 반환합니다.

오류가 발생한 경우 Expect를 호출하지 않으면 컴파일되지만 경고가 표시됩니다.

let f: u32 = File::open("hello.txt"); // File::open()의 반환타입은 Result<T,E>이다.
let f = match f { Ok(file) => file, Err(error) => { panic!
("There was a problem opening the file: {:?}", error) }, }; // 패턴 매칭을 이용하여 위와 같이 에러 핸들링을 할 수 있다.
let f = File::open("hello.txt").unwrap(); // unwrap함수를 호출하는 경우, Err variant 라면 panic!
매크로를 호출한다.
let f = File::open("hello.txt").expect("Failed to open hello.txt"); // expect 함수 역시 panic!
매크로를 호출하지만, panic!
에서 사용되는 메세지보다 우리가 더 이해하기 쉬운 파라미터로 넘긴 에러 메세지로 출력되어 에러 확인이 더 용이하다.

? == 오류 전파의 약어

실패할 수 있는 코드를 호출하는 함수를 작성하는 경우 함수 내에서 오류를 처리하는 대신 호출 코드에 오류를 반환하고 해당 페이지에서 수행할 작업을 결정하도록 할 수 있습니다.

결과 값에 따라. 구문을 적어두면 Ok이면 Ok의 값을 얻을 수 있고 Err이면 Err의 값이 전체 함수로 반환됩니다.

fn read_username_from_file() -> Result<String, io::Error> {
    let mut f = File::open("hello.txt")?;
    let mut s = String::new();
    f.read_to_string(&mut s)?;
    Ok(s)
}

스마트 포인터

스마트 포인터는 포인터처럼 작동하지만 추가 메타데이터 및 기능이 있는 데이터 구조입니다.

예를 들어 참조 횟수가 계산되는 스마트 포인터 유형을 사용하여 소유자 수를 추적하고 더 이상 소유자가 없을 때 데이터를 제거하여 일부 데이터에 대해 여러 소유자를 만들 수 있습니다.

소유권의 차용 개념이 있는 Rust에서 참조와 스마트 포인터의 차이점은 참조는 단지 데이터를 빌린 포인터라는 것입니다.

String수업 Vec<T>와 같은 스마트 포인터는 약간의 메모리가 있으며 이를 조작할 수 있습니다.
또한 이 데이터가 유효한 UTF-8 유형인지 확인하기 위해 용량 및 보증 데이터와 같은 메타데이터가 있습니다.

스마트 포인터 Deref그리고 Drop 속성을 구현하려면 Deref 이 속성을 사용하면 스마트 포인터 구조의 인스턴스가 참조처럼 동작하여 참조 또는 스마트 포인터와 함께 작동하는 코드를 작성할 수 있습니다.

Drop 속성을 사용하면 스마트 포인터 인스턴스가 범위를 벗어날 때 실행되는 코드를 사용자 지정할 수 있습니다.

나무 상자

힙에 데이터를 저장하고 스택에 데이터를 가리키는 포인터가 있습니다.
상자가 해제되면 힙과 스택의 모든 데이터가 해제됩니다.

상자는 다음과 같은 경우에 사용됩니다.

  • 컴파일 시간에 크기를 알 수 없는 유형이 있고 정확한 크기를 알아야 하는 컨텍스트에서 해당 유형의 값을 사용하려는 경우
  • 많은 양의 데이터가 있고 소유권을 이전하려고 하지만 프로세스에서 데이터가 복사되지 않았는지 확인하고 싶습니다.
  • 값을 소유하고 인스턴스화된 유형을 아는 것보다 특정 특성을 구현하는 유형에만 관심이 있는 경우.
  1. 컴파일 타임에 크기를 알 수 없는 유형 중 하나는 재귀 유형입니다.

    재귀 유형의 예 cons list알아 보자

단점 목록

cons 함수는 두 개의 인수를 사용하여 일반적으로 단일 값과 다른 쌍인 새 쌍을 만듭니다.
이러한 쌍을 포함하는 쌍은 목록을 형성합니다.

속기: “to cons x on y”는 항목 x를 새 컨테이너에 삽입한 다음 컨테이너 y를 여기에 삽입하는 식으로 새 컨테이너 인스턴스를 생성하는 것을 의미합니다.

cons 목록의 항목에는 두 개의 항목이 포함되어 있습니다.
현재 요소와 다음 요소의 값입니다.

목록의 마지막 항목은 Nil 라는 값을 포함
cons 목록은 cons 함수를 재귀적으로 호출하여 생성됩니다.

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

Message에 대한 값을 할당하는 데 얼마나 많은 공간이 필요한지 결정하기 위해 Rust는 각 변형을 살펴보고 어떤 것이 가장 많은 공간을 차지하는지 확인합니다.
(어쨌든 하나의 값에만 매핑되기 때문에 가장 큰 변형 값만 보세요)

let list = Cons(1, Cons(2, Cons(3, Nil))); // 비재귀적인 variant 값인데, 무한한 사이즈의 List를 갖기 때문에 아래와 같은 버그가 발생한다.
//help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `List` representable

다음 상황에서 상자포인터이므로 로 정의하면 위와 같은 오류를 고칠 수 있다.

enum List {
    Cons(i32, Box<List>),
    Nil,
}

use List::{Cons, Nil};

fn main() {
    let list = Cons(1,
        Box::new(Cons(2,
            Box::new(Cons(3,
                Box::new(Nil))))));
}

RC == 참조 카운팅을 위한 스마트 포인터

다중 소유권을 활성화하려면 Rust Rc<T>이것은 값이 아직 사용 중인지 여부를 알기 위해 값에 대한 참조 수를 추적하는 데 사용되는 유형입니다.
null 참조가 있는 경우 참조를 무효화하지 않고 값을 가비지 수집할 수 있습니다.

enum List {
    Cons(i32, Rc<List>),
    Nil,
}

use List::{Cons, Nil};
use std::rc::Rc;

fn main() {
    let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
    let b = Cons(3, Rc::clone(&a));
    let c = Cons(4, Rc::clone(&a));
}

각 Cons 변형은 값과 목록을 가리키는 Rc입니다.
b를 생성할 때 Rc는 a의 소유권을 갖는 대신 a를 보유합니다.
참조 수를 1에서 2로 늘리고 a와 b가 Rc이면 clone이 됩니다.
내면의 가치를 공유하세요.
c를 구축하면 참조 수가 2개에서 3개로 증가합니다.
Rc::clone을 호출할 때마다 Rc기존 데이터의 개수는 증가하고 이 데이터에 대한 참조 횟수가 0이 되지 않는 한 메모리는 삭제되지 않습니다.

불변 참조로 Rc읽기 전용이므로 프로그램의 다른 부분 간에 데이터를 교환할 수 있습니다.
Rc의 데이터를 변경해야 하는 경우 Cell 또는 RefCell에서 데이터를 래핑해야 합니다.
만약 RC여러 변경 가능한 참조를 허용하면 데이터 경합 및 데이터 불일치가 발생할 수 있습니다.
내부 가변성 패턴과 불변성 제약 조건이 함께 작동하려면 RcRefCell과 함께 사용할 수 있습니다.
나중에 그 녀석을 알아보자.. 🙂
멀티스레드의 경우 Arc를 사용하고 Rc::strong_count를 호출하여 참조 횟수를 확인할 수 있습니다.