inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

우아한 고성능 프로그래밍 언어 Rust 입문 및 활용

구조체 예제

구조체는 언제나 Heap에 저장되나요??

해결된 질문

418

h23570

작성한 질문수 1

2

사각형 너비와 높이로 면적 구하는 예제에서

struct Rectangcle {
    width : u32,
    height : u32,
}

fn main() {
    let rect = Rectangcle{
        width:20,
        height:30,
    };

    println!("가로가 {}, 세로가 {}인 사각형의 면적은 {}이다.", rect.width, rect.height, area(rect));

    print!("{:?}", rect.width);
}

fn area(rect : Rectangcle)->u32 {
    rect.width*rect.height
}

위와 같이 만들었더니 소유권 이전이 일어나더라고요.

크기가 정해진 자료형으로만 이루어진 튜플이 Stack에 저장되는 것 처럼 Rectangle 구조체는 크기가 정해진 자료형이라 Stack에 저장될거라고 생각했는데 소유권 이전이 일어나는 걸 보면 Heap에 저장되는 건가 싶어서 질문 드립니다.

 

Stack에 저장되는 자료형은 Copy 되고,

Heap에 저장되는 자료형은 소유권 이전이 되는 방식이라고 생각해서 든 의문인데 제가 잘못 알고 있는 부분이 있을까요??

좋은 강의 잘 듣고 있습니다.

rust webassembly

답변 2

0

김대현

예리한 질문 감사드립니다. 덕분에 저도 다시 한번 학습하게 되었습니다.

구현하신 구조체는 스택에 저장되는 것이 맞겠습니다. 구성멤버의 메모리 크기가 컴파일타임에 사전 결정되기 때문에 더욱 가능합니다.

스택과 힙 메모리 어디에 할당되는가를 중요하게 설명드렸기에 혼란을 끼친 것 같습니다.

소유권 이전은 사실 엄밀하게 따지면 소유권의 대상(즉 메모리를 차지하고 있는 데이터)이 복사 되는가 아닌가가 더 중요하다고 볼 수 있습니다. 스택에 위치하는 기본 데이터형(i32 등)은 기본적으로 Copy 트레이트가 구현된 상태이고, 직접 선언하는 Struct는 기본적으로는 Copy트레이트가 구현되지 않습니다.

따라서 복제(Copy)가 발생하지 않고 소유권이 이동되어 버리는 상황인데요, 구현하신 코드에서 해당 구조체에 대해 Copy트레이트를 구현하신다면, 소유권이 이동되지 않고 복사되어 활용 가능합니다.

 

#[derive(Clone, Copy)]
struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let rect = Rectangle {
        width: 20,
        height: 30,
    };

    println!(
        "가로가 {}, 세로가 {}인 사각형의 면적은 {}이다.",
        rect.width,
        rect.height,
        area(rect)
    );

    print!("{:?}", rect.width);
}

fn area(rect: Rectangle) -> u32 {
    rect.width * rect.height
}

이렇게 구현하시면 컴파일됩니다. 첫줄의 derive를 이용해서 Copy트레이트를 구현하였기 때문입니다. 대신 main함수의 스택공간과, area함수의 스택 공간 모두를 중복해서 차지하고 있게 되겠습니다.

다시 정리하면, Heap을 차지하는 데이터라고 하더라도 Copy트레이트를 구현하면 내용이 복사되면서, 소유권 이동이 일어나지 않겠습니다.

중급과정을 제작할 예정인데, 보충해서 잘 설명해보도록 하겠습니다.

수강과 질문 감사드립니다.

 

 

1

h23570

답변 감사드립니다.

덕분에 헷갈렸던 내용이 잘 정리되었습니다.

중급 강의도 기대하고 있겠습니다!!

0

인프런 AI 인턴

안녕하세요, 인프런 AI 인턴입니다.

질문하신 “구조체가 언제나 힙(Heap)에 저장되는가”에 대한 부분과, Rust에서의 소유권 이전 현상에 대해 설명하겠습니다.

Rust에서 struct나 기본 데이터 타입(integer, float, bool 등)은 기본적으로 스택(Stack)에 저장됩니다, 특히 해당 타입의 크기가 컴파일 타임에 결정된다면 스택에 저장됩니다. 예제에서의 Rectangle 구조체는 u32 타입의 widthheight로 구성되어 있고, 이는 컴파일 타임에 크기가 결정되므로 스택에 저장됩니다.

소유권 이전이 일어나는 것은 저장 위치(Stack 또는 Heap)와 직접적인 관련이 없습니다. Rust에서는 소유권 시스템에 따라 변수(또는 값)의 소유자가 단 한 명만 존재할 수 있으며, 이를 통해 메모리 안전성을 보장합니다. 함수에 변수를 전달할 때 소유권이 이전되는 것(move 발생)은 해당 변수가 힙에 저장되었는지 스택에 저장되었는지와는 무관하게 발생할 수 있습니다.

fn area(rect: Rectangle) -> u32 함수에 Rectangle 인스턴스를 인자로 넘기면, 해당 인스턴스의 소유권은 함수로 이전됩니다. 이는 구조체가 힙에 저장되었기 때문이 아니라 Rust의 소유권 규칙 때문입니다. 이러한 소유권 이전을 피하려면, 구조체의 참조를 넘기거나, 해당 타입이 Copy 트레잇을 구현하고 있는지 확인해야 합니다. 기본 데이터 타입들은 대부분 Copy 트레잇을 구현하고 있어 값이 자동으로 복사됩니다. 그러나 구조체는 기본적으로 Copy를 구현하지 않습니다; 명시적으로 구현해 주어야 합니다.

제가 답변을 통해 드릴 수 있는 가장 가까운 내용은 “Integer와 String의 소유권과 복사에 관한 질문”입니다. 이 글에서는 Integer와 String 타입이 Rust에서 어떻게 다루어지는지 설명되어 있으며, 복사와 소유권 전달의 개념에 대한 좋은 예시를 제공합니다. 비록 정확한 질문에 대한 답변은 아니지만, Rust에서의 소유권과 데이터 저장 방식에 대한 이해를 돕는 내용입니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

다음강의 플랜이 어떻게 되실까요?

0

35

1

소스코드

0

32

1

강의 자료 ppt나 pdf 파일은 없을까요?

0

69

1

선생님 ppt자료를 받아서 공부하고 싶습니다.

0

53

2

Rust는 어떻게 컴파일 타임에 dangling reference를 막나요?

0

70

2

강의 추가 계획 질문

0

76

2

소유권 이전과 관련된 질문입니다

0

148

2

&r1 을 써야하는지 r1을 써야하는지?

1

120

1

임대값 수명에 대한 질문

1

122

1

변수 가리기 shadowing 을 듣고 궁금한점이 생겼습니다.

1

154

1

튜플 구조체에서 println! 사용시 에러가 발생합니다.

0

166

1

메모리 관리규칙에서 질문드립니다.

1

210

1

튜플과 구조체 차이 설명에 관한 질문

0

377

1

튜플과 배열 강의 4:50에서 벡터 나중에 설명해주신다고 하셨는데

0

193

1

trait를 인자로 받을 때 &impl과 &dyn차이

1

366

2

Lifecycle 강의에서 두 문자열 슬라이스를 비교해 긴 문자열 슬라이스를 리턴하는 것 관련 질문

0

268

1

혹시 어떤 폰트일까요?

0

457

2

build 오류

0

403

1

웹 어플리케이션 개발에도 잘 사용되나요?

1

458

1

임대값의 수명 강의가 재생이 안되고 있습니다~

0

413

3

임대값의 수명에 대한 강의는 언제쯤 볼 수 있을까요?

0

350

2

문자열 리터럴이 너무 어려워요ㅠㅠ

1

556

1

Integer는 자동으로 copy되서(copy type)(integer 는 stack에 할당되서)

0

367

2

명령어를 입력 한 후 source "$HOME/.cargo/env" 이 명령어를 입력해야 합니다.

0

337

2