개요
- 가비지 콜렉터 없이 메모리 안정성 보장
- 컴파일 타임에 컴파일러가 체크할 규칙들로 구성된 소유권 시스템을 통해 메모리 관리
- 런타임 비용이 발생하지 않음
- 참조자(references)
- &를 사용하여 값을 참조하지만 소유하지는 않는 참조자를 생성
- 참조자가 가리키는 값은 참조자가 스코프 밖으로 벗어났을 때도 메모리가 반납되지 않음
- 빌림(borrowing)
- 함수의 파라미터로 참조자를 만드는 것
- 변수와 마찬가지로 기본적으로는 불변, mut를 사용하면 가변
- 가변 참조자(mutable references)
- &mut를 사용하여 가변성을 부여한 참조자
- 특정 스코프내에 하나만 생성 가능
- 불변 참조자를 가지고 있을 동안에도 생성 불가
- 불변 참조자를 사용하는 동안 값이 변경되면 않되므로 생성 불가
- 불변 참조자는 여러개 생성 가능
- 댕글링 참조자(dangling references)
- 컴파일러가 모든 참조자들이 댕글링 참조자가 되지 않도록 보장
- 컴파일러는 참조자가 스코프 밖으로 벗어나기 전에는 데이터가 스코프 밖으로 벗어나지 않을 것임을 확인
규칙
- 각각의 값은 해당값의 오너(owner)라고 불리는 변수를 갖는다
- 한번에 딱 하나의 오너만 존재 가능하다
- 오너가 스코프 밖으로 벗어나면 값은 버려진다(dropped)(drop 함수 호출)
예제 1
- 코드
-
fn main() {
{
let s1 = String::from("a");
let s2 = s1;
println!("{}", s1);
}
}
- 실행 결과
-
error[E0382]: borrow of moved value: `s1`
--> src/main.rs:6:24
|
3 | let s1 = String::from("a");
| -- move occurs because `s1` has type `String`, which does not implement the `Copy` trait
4 | let s2 = s1;
| -- value moved here
5 |
6 | println!("{}", 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
|
4 | let s2 = s1.clone();
| ++++++++
For more information about this error, try `rustc --explain E0382`.
error: could not compile `test1` (bin "test1") due to previous error
예제 2
- 코드
-
fn main() {
{
let s1 = String::from("a");
let s2 = s1.clone();
println!("{}", s1);
println!("{}", s2);
}
}
- 실행 결과
예제 3
- 코드
-
fn f1(s: String) {
println!("{}", s);
}
fn main() {
let s = String::from("a");
f1(s);
println!("{}", s);
}
- 실행 결과
-
error[E0382]: borrow of moved value: `s`
--> src/main.rs:8:20
|
6 | let s = String::from("a");
| - move occurs because `s` has type `String`, which does not implement the `Copy` trait
7 | f1(s);
| - value moved here
8 | println!("{}", s);
| ^ value borrowed here after move
|
note: consider changing this parameter type in function `f1` to borrow instead if owning the value isn't necessary
--> src/main.rs:1:10
|
1 | fn f1(s: String) {
| -- ^^^^^^ this parameter takes ownership of the value
| |
| in this function
= 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
|
7 | f1(s.clone());
| ++++++++
For more information about this error, try `rustc --explain E0382`.
error: could not compile `test1` (bin "test1") due to previous error
예제 4
- 코드
-
fn f1(s: String) -> String {
s
}
fn main() {
let s = String::from("a");
let s = f1(s);
println!("{}", s);
}
- 실행 결과
예제 5
- 코드
-
fn f1(s: &String) {
println!("{}", s);
}
fn main() {
let s = String::from("a");
f1(&s);
println!("{}", s);
}
- 실행 결과
예제 6
- 코드
-
fn f1(s: &String) {
s.push_str(", b");
}
fn main() {
let s = String::from("a");
f1(&s);
println!("{}", s);
}
- 실행 결과
-
error[E0596]: cannot borrow `*s` as mutable, as it is behind a `&` reference
--> src/main.rs:2:5
|
2 | s.push_str(", b");
| ^^^^^^^^^^^^^^^^^ `s` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
help: consider changing this to be a mutable reference
|
1 | fn f1(s: &mut String) {
| +++
For more information about this error, try `rustc --explain E0596`.
error: could not compile `test1` (bin "test1") due to previous error
예제 7
- 코드
-
fn f1(s: &mut String) {
s.push_str(", b");
}
fn main() {
let mut s = String::from("a");
f1(&mut s);
println!("{}", s);
}
- 실행 결과
예제 8
- 코드
-
fn main() {
let mut s = String::from("a");
let s1 = &mut s;
let s2 = &mut s;
println!("{}", s1);
println!("{}", s2);
}
- 실행 결과
-
error[E0499]: cannot borrow `s` as mutable more than once at a time
--> src/main.rs:5:14
|
4 | let s1 = &mut s;
| ------ first mutable borrow occurs here
5 | let s2 = &mut s;
| ^^^^^^ second mutable borrow occurs here
6 |
7 | println!("{}", s1);
| -- first borrow later used here
For more information about this error, try `rustc --explain E0499`.
error: could not compile `test1` (bin "test1") due to previous error
예제 9
- 코드
-
fn main() {
let mut s = String::from("a");
{
let s1 = &mut s;
s1.push_str(", b");
println!("{}", s1);
}
let s2 = &mut s;
s2.push_str(", c");
println!("{}", s2);
}
- 실행 결과
예제 10
- 코드
-
fn dangle() -> &String {
let s = String::from("a");
&s
}
fn main() {
println!("{}", dangle())
}
- 실행 결과
-
error[E0106]: missing lifetime specifier
--> src/main.rs:1:16
|
1 | fn dangle() -> &String {
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
|
1 | fn dangle() -> &'static String {
| +++++++
For more information about this error, try `rustc --explain E0106`.
error: could not compile `test1` (bin "test1") due to previous error
예제 11
- 코드
-
fn not_dangle() -> String {
let s = String::from("a");
s
}
fn main() {
println!("{}", not_dangle())
}
- 실행 결과