#pragma once
class RefCountable
{
public:
RefCountable(): _refCount(1) {}
virtual ~RefCountable() { std::cout << "die!" << endl; }
int32 GetRefCount() { return _refCount; }
int32 AddRef() { return ++_refCount; }
int32 ReleaseRef() {
int32 refCount = --_refCount;
if (_refCount == 0) {
delete this;
}
return refCount;
}
protected:
Atomic<int32> _refCount;
};
template<typename T>
class TSharedPtr {
public:
TSharedPtr() {}
TSharedPtr(T* ptr) { Set(ptr); }
//복사
TSharedPtr(const TSharedPtr& rhs) {
Set(rhs._ptr);
}
//이동
TSharedPtr(TSharedPtr&& rhs) {
_ptr = rhs._ptr;
rhs._ptr = nullptr;
}
//상속 관계 복사
template<typename U>
TSharedPtr(const TSharedPtr<U>& rhs) {
Set(static_cast<T>(rhs._ptr));
}
~TSharedPtr() { Release(); }
public:
// 복사연산자
TSharedPtr& operator=(const TSharedPtr& rhs) {
if (_ptr != rhs._ptr) {
Release();
Set(rhs._ptr);
}
return *this;
}
// 이동연산자
TSharedPtr& operator=(const TSharedPtr&& rhs) noexcept {
Release();
_ptr = rhs._ptr;
return *this;
}
bool operator==(const TSharedPtr& rhs) const {
return rhs._ptr == _ptr;
}
bool operator!=(const TSharedPtr& rhs) const {
return rhs._ptr != _ptr;
}
bool operator==(const T* ptr) const {
return ptr == _ptr;
}
bool operator!=(const T* ptr) const {
return ptr != _ptr;
}
T& operator*() { return *_ptr; } // (*name).func
const T& operator*() const{ return *_ptr; } // const 객체 -> const 멤버함수만 가능
operator T*() const { return _ptr; } // name* tmp = (name*)obj
T* operator->() { return _ptr; }
const T* operator->() const { return _ptr; }
operator T&() const{ return *_ptr; }
operator T() const{ return *_ptr; }
bool isNull() { return _ptr == nullptr; }
private:
inline void Set(T* ptr) {
_ptr = ptr;
if (ptr)
ptr->AddRef();
}
inline void Release() {
if (_ptr) {
_ptr->ReleaseRef();
_ptr = nullptr;
}
}
private:
T* _ptr = nullptr;
};
스마트 포인터느낌으로 구현한 것이다.
class Wraith : public RefCountable {
public:
int _hp = 150;
int _posX = 0;
int _posY = 0;
};
using WraithRef = TSharedPtr<Wraith>;
class Missile : public RefCountable {
public:
Missile& operator=(const Missile& rhs) {
*this = rhs;
return *this;
}
void SetTarget(WraithRef target) {
_target = target;
target->AddRef();
}
bool Update() {
if (_target == nullptr)
return true;
int posX = _target->_posX;
int posY = _target->_posY;
//TODO 쫓아간다
if (_target->_hp <= 0) {
_target->ReleaseRef();
_target = nullptr;
return true;
}
return false;
}
Wraith* _target = nullptr;
};
using MissileRef = TSharedPtr<Missile>;
int main() {
WraithRef wraith(new Wraith());
wraith->ReleaseRef();
MissileRef missile(new Missile());
missile->ReleaseRef();
missile->SetTarget(wraith);
wraith->_hp = 0;
wraith = nullptr; // nullptr은 자동으로 형변환하기 떄문에
// wraith
while (true) {
if (missile) {
missile->Update();
}
if (!wraith)
break;
}
missile = nullptr;
return 0;
}
wraith = nullptr 부분에서 WraithRef(nullptr)이 생성되고 복사 대입 연산자 혹은 이동 대입 연산자가 호출된다.
'MMOServer' 카테고리의 다른 글
메모리 관련 (0) | 2025.03.27 |
---|---|
Smart_Pointer(C++) (0) | 2025.03.22 |
DeadLock 탐지(C++) (0) | 2025.03.20 |
Read-Write Lock(C++) (0) | 2025.03.19 |
멀티스레드의 메모리 이슈 (0) | 2025.03.13 |