Modern C++ - 스마트포인터(Smart Pointer)

이승덱·2021년 7월 21일

CPP

목록 보기
70/70
#include <iostream>

#include <vector>

#include <list>

#include <deque>

#include <map>

#include <set>

#include<algorithm>

using namespace std;

// Modern C++ (C++11 부터 나온 아이들)

// 스마트 포인터 (smart pointer)

class Knight {

public:

 Knight() { cout << "Knight 생성" << endl; }

 ~Knight() { cout << "Knight 소멸" << endl; }

 void Attack() {

 // weak_ptr은 expired문을 통해 이 객체가 아직 살아있는지 확인(false면 살아있는 것)

 if (_target.expired()==false) {

 // 전환을 통해 shared_ptr로 사용

 shared_ptr<Knight> sptr = _target.lock();

 sptr->_hp -= _damage;

 cout << sptr->_hp << endl;

 }

 }

public:

 int _hp = 100;

 int _damage = 10;

 

 //shared_ptr<Knight> _target = nullptr;

 weak_ptr<Knight> _target;

};

class RefCountBlock {

public:

 int _refCount = 1; //refCount가 0이면 삭제해도 된다

 int _weakCOunt = 1; //weakPointer가 몇개의 객체를 참고하는가?

 //weak_ptr을 통해 그 객체가 날라간지 안날라간지 확인할 수 있는 용도

};

template<typename T>

class SharedPtr {

 // 누구도 포인터를 기억하지 않을 때 삭제를 함

public:

 SharedPtr() {

 }

 SharedPtr(T* ptr):_ptr(ptr) {

 _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--; // delete를 바로 실행하지 않고 refCount를 1 줄여준다

 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()

{

 //Knight* k1 = new Knight();

 //Knight* k2 = new Knight();

 //k1->_target = k2;

 //delete k2; // k2는 사라졌지만 _target은 사라지지 않음 -> 메모리 오염 발생

 //k1->Attack();

 // 기존의 포인터보단 스마트 포인터로 생명주기를 관리하는 것이 좋다.

 // 스마트 포인터 : 포인터를 알맞는 정책에 따라 관리하는 객체 (포인터를 래핑해서 사용)

 // shared_ptr(대표 주자), weak_ptr, unique_ptr

 // shared_ptr : 누구도 포인터를 주시하지 않을 경우에만 삭제

 {

 // SharedPtr<Knight> k1(new Knight()); // Knight를 관리하는 SharePtr;

 // SharedPtr<Knight> k2 = k1;

 /*SharedPtr<Knight> k3;

 {

 SharedPtr<Knight> k4(new Knight());

 k3 = k4;

 }*/

 

 } 

 

 shared_ptr<Knight> k1 = make_shared<Knight>();

 {

 shared_ptr<Knight> k2 = make_shared<Knight>();

 k1->_target = k2; // shared_ptr의 문제 

 k2->_target = k1; // 서로 주시하는 경우 순환 문제가 생겨

 // 메모리가 삭제가 되지 않는 문제가 발생

 k1->Attack();

 //k1->_target = nullptr; // 때문에 모든 사용이 끝난 후 nullptr로 밀어줘야하는 불편함이 생김

 //k2->_target = nullptr; // 이러한 단점을 해결하기 위한 것이 weak_ptr

 } 

 unique_ptr<Knight> uptr = make_unique<Knight>(); // 나만 사용하겠어

 //unique_ptr<Knight> uptr2 = uptr; //안됨

 unique_ptr<Knight> uptr2 = move(uptr); // 사용하고 싶으면 move를 통해 이동해야함

 return 0;

}
profile
공부 기록용 블로그입니다

0개의 댓글