cpp

C++ 동적 메모리 관리

임베디드 친구 2024. 12. 19. 20:43
반응형

C++에서 동적 메모리 관리는 메모리를 효율적으로 사용하고 프로그램의 유연성을 높이기 위해 매우 중요한 개념입니다. 이 글에서는 동적 메모리 관리의 기본 개념과 C++에서 제공하는 주요 기능, 그리고 이를 활용하는 방법에 대해 살펴보겠습니다.

동적 메모리란?

동적 메모리는 프로그램 실행 중에 필요에 따라 할당하거나 해제할 수 있는 메모리입니다. C++에서는 newdelete 키워드를 사용하여 동적 메모리를 관리할 수 있습니다. 동적 메모리는 보통 힙(Heap) 영역에서 관리되며, 고정된 크기의 스택 메모리와는 달리 유동적으로 사용할 수 있습니다.

동적 메모리 할당

동적 메모리를 할당하려면 new 키워드를 사용합니다. 예를 들어, 정수형 변수를 동적으로 할당하는 방법은 다음과 같습니다:

int* ptr = new int; // 정수형 메모리 할당
*ptr = 42;         // 할당된 메모리에 값 저장

std::cout << "값: " << *ptr << std::endl; // 출력: 값: 42

배열도 동적으로 할당할 수 있습니다:

int* arr = new int[5]; // 정수형 배열 할당

for (int i = 0; i < 5; ++i) {
    arr[i] = i * 10;
}

for (int i = 0; i < 5; ++i) {
    std::cout << arr[i] << " ";
}
// 출력: 0 10 20 30 40

동적 메모리 해제

동적 메모리를 사용한 후에는 반드시 해제해야 합니다. 그렇지 않으면 메모리 누수가 발생할 수 있습니다. delete 키워드를 사용하여 단일 메모리를 해제하고, delete[]를 사용하여 배열을 해제합니다.

delete ptr;      // 단일 메모리 해제
delete[] arr;    // 배열 메모리 해제

메모리를 해제한 후에는 해당 포인터를 nullptr로 초기화하여 잘못된 접근을 방지하는 것이 좋습니다:

ptr = nullptr;
arr = nullptr;

스마트 포인터

C++11부터는 스마트 포인터를 사용하여 동적 메모리를 더욱 안전하게 관리할 수 있습니다. 스마트 포인터는 메모리 관리의 부담을 줄이고, 메모리 누수를 방지하는 데 큰 도움을 줍니다.

std::unique_ptr

std::unique_ptr는 소유권이 단일 객체에만 제한되는 스마트 포인터입니다:

#include <memory>
#include <iostream>

int main() {
    std::unique_ptr<int> ptr = std::make_unique<int>(10);
    std::cout << "값: " << *ptr << std::endl; // 출력: 값: 10

    return 0; // ptr은 범위를 벗어나면 자동으로 메모리 해제
}

std::shared_ptr

std::shared_ptr는 여러 객체가 메모리를 공유할 수 있는 스마트 포인터입니다:

#include <memory>
#include <iostream>

int main() {
    std::shared_ptr<int> ptr1 = std::make_shared<int>(20);
    std::shared_ptr<int> ptr2 = ptr1; // 메모리 공유

    std::cout << "값: " << *ptr1 << ", 참조 횟수: " << ptr1.use_count() << std::endl;
    // 출력: 값: 20, 참조 횟수: 2

    return 0; // 참조 횟수가 0이 되면 메모리 자동 해제
}

std::weak_ptr

std::weak_ptrstd::shared_ptr와 함께 사용되며, 메모리 소유권을 공유하지 않고도 객체에 접근할 수 있습니다. 순환 참조를 방지하는 데 유용합니다.

#include <memory>
#include <iostream>

struct Node {
    std::shared_ptr<Node> next;
    std::weak_ptr<Node> prev;
};

int main() {
    auto node1 = std::make_shared<Node>();
    auto node2 = std::make_shared<Node>();

    node1->next = node2;
    node2->prev = node1;

    return 0; // 순환 참조 없이 안전하게 메모리 해제
}

동적 메모리 관리의 주의점

  1. 메모리 누수 방지: 동적으로 할당한 메모리는 반드시 해제해야 합니다.
  2. 해제 후 포인터 초기화: 메모리를 해제한 포인터는 nullptr로 초기화하여 잘못된 접근을 방지합니다.
  3. 스마트 포인터 사용: 가능하다면 스마트 포인터를 사용하여 메모리를 자동으로 관리합니다.

결론

C++에서 동적 메모리 관리는 강력한 기능이지만, 잘못된 사용은 심각한 버그와 성능 문제를 초래할 수 있습니다. 따라서 newdelete를 사용할 때 주의하고, C++11 이후에는 스마트 포인터를 적극적으로 활용하는 것이 좋습니다. 동적 메모리를 올바르게 관리하여 안정적이고 효율적인 프로그램을 작성해보세요!

반응형

'cpp' 카테고리의 다른 글

C++ 상속과 다형성  (0) 2024.12.19
C++ 클래스와 객체  (0) 2024.12.19
C++ 포인터와 참조  (0) 2024.12.18
C++ 배열과 문자열  (0) 2024.12.18
C++ 함수  (0) 2024.12.18