스마트 포인터 따라해보기

메모리 누수를 방지하고, 객체의 생명 주기를 명확하게 하기 위해 다양한 스마트 포인터가 사용된다.

과거 ComPtr을 다뤄봤지만, 그냥 C++에서 지원하기에 사용해봤던 것이다.

이번에는 직접 한번 구현해보고 어떤 과정으로 스마트하게 진행되는지 알아보자.

코드 분석

#pragma once

template<typename T>
class Ptr
{
private:
    T* Asset;

public:
    void operator = (T* asset)
    {
        Asset = asset;
    }

public:
    Ptr()
        : Asset(nullptr)
    {
    }

    Ptr(T* asset)
        : Asset(asset)
    {
        if (nullptr != Asset)
            Asset->AddRef();
    }

    ~Ptr()
    {
        if (nullptr != Asset)
            Asset->Release();
    }
};

핵심 기능

  • 객체 참조 관리

    • 생성자에서 AddRef() 호출하여 참조 카운트 증가

    • 소멸자에서 Release() 호출하여 참조 카운트 감소

  • 삽입 연산자 (=) 오버로딩

    • 외부에서 T* 타입의 객체를 전달 받아 내부 포인터를 설정

사용 방법

예제 코드

class RefCountedObject
{
private:
    int RefCount;

public:
    RefCountedObject() : RefCount(0) {}

private:
    void AddRef()
    {
        ++RefCount;
    }

    void Release()
    {
        if (--RefCount == 0)
            delete this;
    }
    
    template<typename T> // 템플릿 클래스 프렌드 정의
    friend class Ptr;
};

int main()
{
    Ptr<RefCountedObject> pObj = new RefCountedObject();

    // 객체가 자동으로 메모리 관리됨
    return 0;
}

용도

  • 동적 할당된 객체 관리: new 연산자를 통해 생성된 객체의 생명 주기 관리
  • 참조 카운팅 기반 메모리 관리: 객체가 더 이상 사용되지 않으면 자동으로 해제
  • 안전한 메모리 관리: 명시적인 delete 호출 없이 객체 수명을 보장

개선 가능 사항

현재 Ptr 클래스는 복사 연산자를 제공하지 않으며, 할당 시 기존 객체의 참조 해제가 필요하다.

태그:

카테고리:

업데이트:

댓글남기기