Rust 언어에서 가장 특이한 소유권 개념.
전통적인 언어가 함수 인자로 값을 전달 할 때 기본적인 동작이 얕은 복사나 깊은 복사를 수행한다
그러나 Rust는 소유권 이동을 한다.
struct MyBag {
item: i32,
}
fn move_test(bag: MyBag) {
println!("{}", bag.item);
}
fn main() {
{
let bag = MyBag { item: 32i32 };
move_test(bag);
println!("{}", bag.item);
}
{
let bag = MyBag { item: 32i32 };
let bag2 = &bag;
move_test(bag);
println!("{}", bag2.item);
}
}
그리고 위 코드를 컴파일 하면 다음과 같은 컴파일 에러를 발생 시킨다.
error[E0382]: borrow of moved value: `bag`
--> src\main.rs:13:24
|
11 | let bag = MyBag { item: 32i32 };
| --- move occurs because `bag` has type `MyBag`, which does not implement the `Copy` trait
12 | move_test(bag);
| --- value moved here
13 | println!("{}", bag.item);
| ^^^^^^^^ value borrowed here after move
|
Rust 컴파일러가 인스턴스의 생명 주기를 관리하여 문제가 발생할 경우 바로 에러를 발생 시킨다.
Rust는 적어도 소유권 이동을 안전하게 사용할 수 있는 환경을 준비를 한 셈이다.
다른 언어는 어떻까 ? C++에는 rvalue 연산자, 스마트 포인터와 함께 이동 연산에 대한 개념이 있다.
#include <iostream>
#include <memory>
void func(std::unique_ptr<int> pt) {
std::cout << *pt << std::endl;
}
int main() {
auto pt = std::make_unique<int>(10);
func(std::move(pt));
std::cout << *pt << std::endl;
return 0;
}
g++ main.cpp -Wall
컴파일 경고 수준을 높여 보았지만 어떤 에러/경고가 없었다.
C++에서 소유권 이동에 대한 개념은 어떤 영역에서 활용 가치가 있는지 아직은 사례를 찾지 못하였다.
Rust의 C++ 소유권 이동과 다른 특이한 점은 stack 메모리에 대해서 소유권 이동이 가능 하다는 점이다
pub struct Foo {
x: i32,
}
pub fn do_something(f: Foo) {
f.x * 100;
// f가 여기서 drop 됩니다
}
pub fn main() {
let foo = Foo { x: 42 };
// foo가 do_something으로 move 됩니다
do_something(foo);
// foo는 더 이상 사용할 수 없습니다
}
do_something 함수를 호출할때 별도의 스택 프레임을 생성하지 않았다.
C++과 같이 RVO 최적화가 발생 한것 같다.
하지만 이것만 보고 소유권 이동이 메모리 복사를 하지 않는다고 결단 내릴 수 는 없다.
전달될 메모리가 커지면 do_something 내에서도 스택 프레임을 생성하여 main 함수에서 전달된 인자를 복사 하는 모습을 볼 수 있따.
pub struct Foo {
x: i64,
y: i64,
z: i64,
}
pub fn do_something(f: Foo) {
let s = f.x + f.y + f.z;
// f가 여기서 drop 됩니다
}
pub fn main() {
let foo = Foo {
x: 1,
y: 2,
z: 3,
};
// foo가 do_something으로 move 됩니다
do_something(foo);
// foo는 더 이상 사용할 수 없습니다
}
main 함수에서 do_something 함수의 스택 프레임까지 미리 만들어 놓고 여기에 값을 복사 하는 것으로 보인다.
스택 메모리에서 소유권 이동을 할때 메모리 복사가 발생 할 수 있음을 유의해야 한다.
이 글 역시 stack 메모리의 소유권 이전은 복사를 통해 구현되고 있음을 확인할 수 있다
stack 메모리의 소유권 이전은 메모리 복사임을 명시해야 한다