프로그래밍/Modern c++
스마트 포인터
오늘의논리
2023. 3. 6. 22:37
728x90
스마트 포인터 : 포인터를 알맞은 정책에 따라 관리하는 객체( 포인터를 래핑해서 사용)
shared_ptr, weak_ptr, unique_ptr 이렇게 3가지가 있으며
Shared_ptr 구현
class Knight
{
public:
Knight()
{
cout << "Knight 생성" << endl;
}
~Knight()
{
cout << "Knight 소멸" << endl;
}
void Attack()
{
if (_target)
{
_target->_hp -= _damage;
}
cout << "HP : " << _target->_hp << endl;
}
public:
int _hp = 100;
int _damage = 10;
Knight* _target = nullptr;
};
class RefCountBlock
{
public:
public:
int _refCount = 1;
};
template<typename T>
class SharedPtr // 어느 누구도 기억하지 않을때 삭제
{
public:
SharedPtr() {}
SharedPtr(T* ptr) : _ptr(ptr)
{
if (_ptr != nullptr)
{
_block = new RefCountBlock();
cout << "RefCount : " << _block->_refCount << endl;
}
}
SharedPtr(const SharedPtr& sptr) : _ptr(sptr._ptr), _block(sptr._block)
{
if (_ptr != nullptr)
{
_block->_refCount++;
cout << "RefCount : " << _block->_refCount << endl;
}
}
void operator=(const SharedPtr& sptr)
{
_ptr = sptr._ptr;
_block = sptr._block;
if (_ptr != nullptr)
{
_block->_refCount++;
cout << "RefCount : " << _block->_refCount << endl;
}
}
~SharedPtr()
{
if (_ptr != nullptr)
{
_block->_refCount--;
cout << "RefCount : " << _block->_refCount << endl;
if (_block->_refCount == 0)
{
delete _ptr;
delete _block;
cout << "delete data" << endl;
}
}
}
public:
T* _ptr = nullptr;
RefCountBlock* _block = nullptr;
};
int main()
{
SharedPtr<Knight> k2;
{
SharedPtr<Knight> k1(new Knight());
k2 = k1;
}
return 0;
}
이런식으로 구현되어 있다고 생각하면됨
그래서 shared_ptr을 사용한다면
Knight 클래스에서 타켓을
shared_ptr<Knight> _target = nullptr;
로 해주고
int main()
{
shared_ptr<Knight> k1 = make_shared<Knight>();
{
shared_ptr<Knight>k2 = make_shared<Knight>();
k1->_target = k2;
}
k1->Attack();
return 0;
}
이렇게 한다면 중괄호 밖을 나와도 k2가 사라지지 않고 어택함수가 제대로 활용됨
Weak_ptr
shared_ptr<Knight>k1 = make_shared<Knight>();
shared_ptr<Knight>k2 = make_shared<Knight>();
k1->_target = k2;
k2->_target = k1;
이러한 상황에선 순환이 되서 메모리가 사라지지 않음 그렇기에 Weak_ptr이 필요
using namespace std;
class Knight
{
public:
Knight()
{
cout << "Knight 생성" << endl;
}
~Knight()
{
cout << "Knight 소멸" << endl;
}
void Attack()
{
if (_target.expired() == false)
{
shared_ptr<Knight>sptr = _target.lock();
sptr->_hp -= _damage;
cout << "HP : " << sptr->_hp << endl;
}
}
public:
int _hp = 100;
int _damage = 10;
weak_ptr<Knight> _target;
};
class RefCountBlock
{
public:
int _refCount = 1;
int _weakCount = 1;
};
template<typename T>
class SharedPtr // 어느 누구도 기억하지 않을때 삭제
{
public:
SharedPtr() {}
SharedPtr(T* ptr) : _ptr(ptr)
{
if (_ptr != nullptr)
{
_block = new RefCountBlock();
cout << "RefCount : " << _block->_refCount << endl;
}
}
SharedPtr(const SharedPtr& sptr) : _ptr(sptr._ptr), _block(sptr._block)
{
if (_ptr != nullptr)
{
_block->_refCount++;
cout << "RefCount : " << _block->_refCount << endl;
}
}
void operator=(const SharedPtr& sptr)
{
_ptr = sptr._ptr;
_block = sptr._block;
if (_ptr != nullptr)
{
_block->_refCount++;
cout << "RefCount : " << _block->_refCount << endl;
}
}
~SharedPtr()
{
if (_ptr != nullptr)
{
_block->_refCount--;
cout << "RefCount : " << _block->_refCount << endl;
if (_block->_refCount == 0)
{
delete _ptr;
//delete _block; //블록을 없애지 않음
cout << "delete data" << endl;
}
}
}
public:
T* _ptr = nullptr;
RefCountBlock* _block = nullptr;
};
int main()
{
shared_ptr<Knight>k1 = make_shared<Knight>();
shared_ptr<Knight>k2 = make_shared<Knight>();
k1->_target = k2;
k2->_target = k1;
k1->Attack();
return 0;
}
Unique_ptr
나만 이세상에서 이 포인터를 가지고 있을거임 이라는 의미
unique_ptr<Knight> uptr = make_unique<Knight>();
unique_ptr<Knight> uptr2 = uptr; // 불가
unique_ptr<Knight> uptr2 = move(uptr); // 가능(이동론을 통해)
728x90