반응형
Rust의 값 전달(Passing Arguments by Value) 완벽 가이드
소개
Rust에서 함수에 인자를 전달하는 방식 중 가장 기본이 되는 '값 전달(Pass by Value)'에 대해 자세히 알아보겠습니다. Rust의 독특한 소유권 시스템과 함께 이해하면 더욱 효과적인 코드를 작성할 수 있습니다.

기본 개념
Rust에서 값을 전달할 때는 기본적으로 소유권이 이전됩니다. 이것이 Rust의 가장 큰 특징 중 하나입니다.
fn main() {
let name = String::from("Alice");
print_name(name);
// println!("{}", name); // 🚫 컴파일 에러! name의 소유권이 이전됨
}
fn print_name(n: String) {
println!("Name: {}", n);
}
기본 타입(Primitive Types)의 값 전달
기본 타입은 Copy 트레이트를 구현하고 있어 값이 복사됩니다.
fn main() {
let number = 42;
multiply_by_two(number);
println!("Original number: {}", number); // 여전히 42 사용 가능!
}
fn multiply_by_two(n: i32) -> i32 {
n * 2
}
구조체의 값 전달
#[derive(Debug)]
struct Person {
name: String,
age: u32,
}
fn main() {
let person = Person {
name: String::from("Bob"),
age: 30,
};
print_person(person);
// println!("{:?}", person); // 🚫 컴파일 에러! person의 소유권이 이전됨
}
fn print_person(p: Person) {
println!("Person: {:?}", p);
}
Copy 트레이트 구현하기
구조체에 Copy 트레이트를 구현하여 값 복사가 가능하게 만들 수 있습니다.
#[derive(Debug, Copy, Clone)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 10, y: 20 };
print_point(point);
println!("Original point: {:?}", point); // 여전히 사용 가능!
}
fn print_point(p: Point) {
println!("Point: {:?}", p);
}
튜플과 배열의 값 전달
튜플과 배열도 기본 타입처럼 처리될 수 있습니다.
fn main() {
// 튜플 예제
let coords = (10, 20);
process_coordinates(coords);
println!("Original coords: {:?}", coords); // Copy 트레이트 구현으로 사용 가능
// 배열 예제
let numbers = [1, 2, 3, 4, 5];
sum_array(numbers);
println!("Original array: {:?}", numbers); // 여전히 사용 가능
}
fn process_coordinates(coords: (i32, i32)) {
println!("Processing coordinates: {:?}", coords);
}
fn sum_array(arr: [i32; 5]) -> i32 {
arr.iter().sum()
}
값 전달과 소유권 이전을 함께 사용하기
실제 애플리케이션에서는 값 전달과 소유권 이전을 적절히 혼합하여 사용합니다.
#[derive(Debug)]
struct User {
name: String,
settings: UserSettings,
}
#[derive(Debug, Copy, Clone)]
struct UserSettings {
dark_mode: bool,
notifications: bool,
}
fn main() {
let user = User {
name: String::from("Charlie"),
settings: UserSettings {
dark_mode: true,
notifications: false,
},
};
// settings는 Copy 가능하므로 복사됨
process_settings(user.settings);
// name은 String이므로 소유권 이전
process_user(user);
// println!("{:?}", user); // 🚫 컴파일 에러!
}
fn process_settings(settings: UserSettings) {
println!("Processing settings: {:?}", settings);
}
fn process_user(user: User) {
println!("Processing user: {:?}", user);
}
값 반환하기
함수에서 값을 반환할 때도 소유권이 이전됩니다.
fn main() {
let name = create_user_name();
println!("Created name: {}", name);
// name의 소유권을 가짐
}
fn create_user_name() -> String {
String::from("David")
}
성능 고려사항
값 전달 시 크기가 큰 데이터의 경우 성능에 영향을 줄 수 있습니다.
#[derive(Debug)]
struct LargeData {
buffer: [u8; 1000000], // 1MB 크기의 배열
}
fn main() {
let data = LargeData {
buffer: [0; 1000000],
};
// 큰 데이터를 값으로 전달하면 비효율적일 수 있음
process_large_data(data);
}
fn process_large_data(data: LargeData) {
println!("Processing large data...");
}
실전 팁과 베스트 프랙티스
- 작은 크기의 기본 타입은 값으로 전달
- 큰 구조체나 문자열은 참조로 전달
- Copy 트레이트 구현은 작은 구조체에만 사용
- 소유권 이전이 필요한 경우 명시적으로 값 전달 사용
fn main() {
// 기본 타입: 값으로 전달
let number = 42;
process_number(number);
// 큰 데이터: 참조로 전달
let text = String::from("Hello, World!");
process_text(&text);
println!("Can still use text: {}", text);
}
fn process_number(n: i32) {
println!("Number: {}", n);
}
fn process_text(t: &String) {
println!("Text: {}", t);
}
결론
Rust의 값 전달 시스템은 소유권 개념과 밀접하게 연관되어 있습니다. 기본 타입의 복사, 구조체의 소유권 이전, Copy 트레이트 구현 등을 적절히 활용하면 안전하고 효율적인 코드를 작성할 수 있습니다. 특히 성능과 메모리 사용을 고려할 때 값 전달 방식을 신중히 선택하는 것이 중요합니다.
반응형
'Rust' 카테고리의 다른 글
Rust에서 정규 표현식 마스터하기 (0) | 2025.03.04 |
---|---|
[Rust] 포인터의 종류와 사용방법 (0) | 2023.12.11 |
[Rust] Option<T> 의 사용방법에 대하여 (2) | 2023.12.06 |
Rust in Jupyter notebook (0) | 2023.12.04 |
[Rust] Clap과 커맨드 라인 argument 다루기 (0) | 2023.09.07 |