15.1 이동의 의미와 스마트 포인터
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; }
};