Rust 기본 : 벡터 (Vector)
러스트에서 제공하는 Vec<T>타입은 동적 배열이다.
- 동적으로 크기 조정 가능하며 Vec<T>는 T 타입으로 고정되어 타입 안전하다.
- 0부터 시작하는 인덱스로 접근 가능하다. ex) v[0]
- 반복자(iterator)와 for 루프를 통해 각 요소에 접근할 수 있다.
Vector 생성 방법 1 : Vec::new()
벡터는 동일한 타입 요소를 가지는 동적 배열이다. 그러나 배열과 달리 힙에 할당된다.
fn main() {
// 빈 벡터 생성
let v: Vec<String> = Vec::new();
let mut v = Vec::new();
// 생성한 스트링 소유권은 vector로 이동한다.
// -> vector가 삭제될 때 내부 모든 스트링 소유권도 연쇄 삭제된다.
v.push(String::from("One"));
v.push(String::from("Two"));
v.push(String::from("Three"));
} // vector dropped.
Vector 생성 방법 2 : 매크로 vec!
fn main() {
let v2 = vec![1, 2, 3];
}
생성한 벡터에 접근 방법 1 : &v[0]
fn main() {
// 생성 방법 2
let v2 = vec![1, 2, 3];
//let s = v[0]; // 백터 스트링 소유권을 밖으로 이동할 수 없다.
let s = &v[0]; // 그러나 참조(borrowing)는 인덱스를 초과하면 panic 발생.
// 안전하게 소유권을 이전하려면 인덱스를 remove 한다.
// 모든 요소의 인덱스가 앞으로 당겨진다.
let s = v.remove(0);
}
생성한 벡터에 접근 방법 2 : v.get(0)
fn main() {
// 생성 방법 2
let v2 = vec![1, 2, 3];
// 안전하다!
let s = v.get(0);
if let Some(e) = s {
println!("{e}");
}
// 깔끔하게 안전하다!
if let Some(e) = v.get(0) {
println!("{e}");
}
}
생성한 벡터에 접근 방법 3 : iterator
fn main() {
let v = vec![
String::from("One"),
String::from("Two"),
String::from("Three")
];
// &mut v : ownership은 그대로 두고 스트링 수정.
for s in &mut v {
s.push_str("!!");
}
for s in &v {
println!("{s}");
}
}
벡터 요소 값으로 옮기기
fn main() {
let v = vec![
String::from("One"),
String::from("Two"),
String::from("Three")
];
let mut v3 = vec![];
// v 백터 데이터를 v3 백터로 소유권 이동(ownership move)
// v의 syntax sugar는 v.into_iter(), 별로 달지 않은데... 이런 게 러스트 맛?
for s in v.into_iter() { // v == v.into_iter()
v3.push(s);
}
// v의 모든 요소 소유권은 이동하였다. 더이상 접근은 유효하지 않다.
//let i = v.get(0); // borrow of moved value
}
소유권 이동 없이 복사하려면 clone() 한다.
fn main() {
let v = vec![
String::from("One"),
String::from("Two"),
String::from("Three")
];
let mut v3 = vec![];
for s in (&v).into_iter() {
v3.push(s.clone());
}
// clone() 하였기 때문에 접근 가능하다.
let i = v.get(0);
}
위 예제들은,
소유권 이동 관계를 섬세하게 이해하기 좋다.
아래 코드는 어떤 에러가 나는가?
fn main() {
let mut v = vec![
String::from("One"),
String::from("Two"),
String::from("Three")
];
let mut v3 = vec![];
for s in (&v).into_iter() { // immutable borrowing
v3.push(s);
}
v.remove(0); // error : mutable borrowing
let i = v3.get(0); // v3의 0번 인덱스는 유효하지 않은 값일 텐데 사전에 error 처리!
}
remove 메소드는 스스로를 가변 참조 한다.
for 루프에서 &v로 불변 참조 값을 전달했는데 v.remove()로 가변 참조하여 요소를 삭제 시도하면서 러스트 소유권 규칙을 위반하였다.
러스트 소유권 규칙.
- 각 값은 해당 값을 소유하는 변수를 가진다.
- 값은 한 번에 하나를 가변 참조 하거나 여러 개의 불변 참조를 가질 수 있다. (둘다 적용 불가!)
- 참조는 항상 유효해야한다.
'개발 > 러스트 (Rust)' 카테고리의 다른 글
Rust 기본 : 상위 특성 (Supertraits) (0) | 2024.09.19 |
---|---|
Rust 기본 : 특성 제약 (Traits Bounds) (0) | 2024.09.12 |
Rust 기본 : 특성 (Traits) (0) | 2024.09.07 |
Rust 기본 : 일반화 (Generics) (0) | 2024.09.03 |
Rust 기본 : 결과 열거형 (Result enum) (0) | 2024.08.21 |
Rust 기본, 옵션 열거형 (Option enum) (0) | 2024.08.17 |
Rust 기본, 패턴 매칭 표현식 (Match expression) (0) | 2024.08.13 |
Rust 기본, 열거형 (Enumerations) (0) | 2024.08.10 |