기본 포인터 vs 스마트 포인터?

기본 포인터

 

기본 포인터는 동적으로 할당된 메모리를 직접 관리해야 합니다. 만약 개발자가 delete를 호출하지 않으면 메모리 누수가 발생합니다.

 

이 메모리 누수를 해결하기 위해 나온 것이 스마트 포인터 입니다.

 

스마트 포인터는 자동으로 메모리 해제를 처리합니다.

스마트 포인터 객체가 더 이상 필요 없게 되면(스코프를 벗어나면) 내부적으로 메모리를 자동으로 해제합니다.

#include <iostream>
#include <memory>  // 스마트 포인터를 사용하기 위해 필요
using namespace std;

int main() {
    unique_ptr<int> ptr = make_unique<int>(42);  // 스마트 포인터 생성
    cout << *ptr << endl;  // 출력: 42
    // 자동으로 메모리 해제 (delete 필요 없음)
    return 0;
}

 

주요포인터의 종류는 std::unique_ptr, std::shared_ptr, 그리고 std::weak_ptr가 있습니다.

 

 

 std::unique_ptr독점 소유(Exclusive Ownership)

#include <iostream>#include <memory>class Toy
{
public:
    Toy() { std::cout << "새 장난감이 만들어졌어요!" << std::endl; }
    ~Toy() { std::cout << "장난감이 없어졌어요..." << std::endl; }
};

int main()
{
    // unique_ptr이라는 상자에 장난감을 넣어요
    std::unique_ptr<Toy> myToy = std::make_unique<Toy>();

    // 상자의 소유권을 친구에게 넘겨요 (myToy는 이제 장난감을 잃어요)
    std::unique_ptr<Toy> friendsToy = std::move(myToy);

    if (!myToy)
    {
        std::cout << "나는 이제 장난감이 없어!" << std::endl;
    }

    // 프로그램 종료 시 friendsToy도 범위를 벗어나며 장난감이 해제됩니다
    return 0;
}

  • 독점 소유: 동일한 객체를 다른 unique_ptr이 소유할 수 없습니다.
  • 이동(Transfer) 가능: 소유권은 복사되지 않고 이동할 수 있습니다 (std::move 사용).
  • 자동 해제: 포인터가 범위를 벗어나면 메모리가 자동으로 해제됩니다.

 

독점이 있다면 공동도 있지 않을까?

std::shared_ptr공유 소유(Shared Ownership)

 

  • 특징: 한 스마트 포인터만 객체를 소유할 수 있음.
  • 다른 사람에게 소유권을 넘길 수는 있지만, 복사할 수는 없음.

#include <iostream>#include <memory>class Toy
{
public:
    Toy() { std::cout << "새 장난감이 만들어졌어요!" << std::endl; }
    ~Toy() { std::cout << "장난감이 없어졌어요..." << std::endl; }
};

int main()
{
    // 여러 사람이 장난감을 공유할 수 있는 상자
    std::shared_ptr<Toy> toyBox1 = std::make_shared<Toy>();

    {
        // 다른 친구가 같은 장난감을 공유해요
        std::shared_ptr<Toy> toyBox2 = toyBox1;
        std::cout << "두 사람이 장난감을 가지고 있어요!" << std::endl;
    } // toyBox2가 소멸되었지만 toyBox1은 여전히 장난감을 가지고 있어요

    std::cout << "이제 한 사람만 장난감을 가지고 있어요!" << std::endl;

    // toyBox1이 범위를 벗어나면 장난감이 해제됩니다
    return 0;
}

 

std::weak_ptr약한 참조(Weak Reference)

 

 

  • 특징: 객체를 참조하지만 소유권이 없음.
  • 주로 순환 참조 문제를 해결할 때 사용.

#include <iostream>#include <memory>class Toy
{
public:
    Toy() { std::cout << "새 장난감이 만들어졌어요!" << std::endl; }
    ~Toy() { std::cout << "장난감이 없어졌어요..." << std::endl; }
};

int main()
{
    // shared_ptr로 장난감을 소유하는 상자
    std::shared_ptr<Toy> toyBox = std::make_shared<Toy>();

    // weak_ptr로 장난감이 여전히 있는지 확인할 수 있어요
    std::weak_ptr<Toy> weakFriend = toyBox;

    if (auto sharedToy = weakFriend.lock())  // shared_ptr로 변환 성공
    {
        std::cout << "장난감이 여전히 있어요, 내가 볼 수 있어요!" << std::endl;
    }
    else
    {
        std::cout << "장난감이 없어졌어요..." << std::endl;
    }

    // toyBox가 소멸되면 장난감도 해제됩니다
    toyBox.reset();

    if (auto sharedToy = weakFriend.lock())  // shared_ptr로 변환 실패
    {
        std::cout << "장난감이 여전히 있어요, 내가 볼 수 있어요!" << std::endl;
    }
    else
    {
        std::cout << "장난감이 없어졌어요..." << std::endl;
    }

    return 0;
}

 

스마트 포인터 요약

스마트 포인터특징비유

unique_ptr 한 객체를 하나의 스마트 포인터만 소유. 복사 불가능, 소유권 이동 가능. "자동차 열쇠는 한 사람만 가질 수 있음."
shared_ptr 여러 스마트 포인터가 객체를 공유. 마지막 포인터가 소멸될 때 메모리 해제. "여러 명이 공동으로 집을 소유함."
weak_ptr 객체를 참조하지만 소유권 없음. 주로 shared_ptr와 함께 순환 참조를 방지하는 데 사용. "집을 빌려 쓰는 사람처럼, 소유하지는 않음."