Resource.h

#pragma once

#include <iostream>

class Resource
{
public:
	int m_data[100];
	
public:
	Resource()
	{
		std::cout << "Resource constructed" << "\n";
	}
    ~Resource()
    {
        std::cout << "Resource destroyed" << "\n";
    }
};

cpp file

#include <iostream>
#include "Resource.h"
#include "AutoPtr.h"

using namespace std;

// RAII : resource acquistion is initialization

void doSomething()
{
    try
    {
        //Resource *res = new Resource; // dull pointer // delete를 수동으로 해줘야 하는 포인터
        //AutoPtr<Resource> res = new Resource; // smart pointer
        AutoPtr<Resource> res(new Resource); // early return 하더라도 소멸자 작동
		
        // work with res
		if (true)
        {
            throw -1; // exception
        }
        
        //delete res; // class안에서 삭제하기 때문에 필요 없다.
    }
    catch (...)
    {
    }
    return;
}

int main()
{
    // doSomething();
    // 오토 포인터의 한계
    AutoPtr<Resource> res1(new Resource);
    AutoPtr<Resource> res2;
    
    cout << std::boolalpha;
    
    cout << res1.m_ptr << "\n";
    cout << res2.m_ptr << "\n";
    
    res2 = res1; // 대입을 해주면 멤버 포인터 복사. // move semantics
    
    cout << res1.m_ptr << "\n";
    cout << res2.m_ptr << "\n"; // 에러 발생. res1에서 소멸자가 발생해서 사라졌는데, res2에서도 같은 것을 삭제하려고 하니 런타임 에러 발생.
    
    return 0;
}

AutoPtr.h

#pragma once

#include <iostream>

template<class T>
class AutoPtr
{
public:
    T *m_ptr = nullptr;
    
public:
    AutoPtr(T *ptr = nullptr)
        : m_ptr(ptr)
    {
    }
    
    ~AutoPtr()
    {
        if (m_ptr != nullptr) delete m_ptr; // null ptr이 아니면 삭제
    }
    
    AutoPtr(AutoPtr &a)
    {
        m_ptr = a.m_ptr;
        a.m_ptr = nullptr; // 첫번째 포인터의 메모리 주소 갖고왔으니 nullptr로 변경
    }
    
    AutoPtr& operator = (AutoPtr &a)
    {
        if (&a == this)
            return *this;
        
        delete m_ptr;
        m_ptr = a.m_ptr;
        a.m_ptr = nullptr; // 소유권 이전!
        return *this;
    }
    
    
    T& operator *() const { return *m_ptr; }
    T* operator-> () const { return m_ptr; }
    bool isNull() const { return m_ptr == nullptr; }
};