[C++] smart pointer
Smart Pointer
인프런 Rookiss님의 'Part1: C++ 프로그래밍 입문' 강의를 기반으로 정리한 필기입니다.
😎[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문 강의 들으러 가기!
Dangling Pointer
더보기
#include <iostream>
using namespace std;
#include <vector>
#include <list>
#include <deque>
#include <map>
#include <set>
#include <algorithm>
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;
};
int main()
{
Knight* k1 = new Knight();
Knight* k2 = new Knight();
k1->_target = k2;
delete k2; //k2를 지운다고 _target이 nullptr이 되는것은 아니다. 이것으로 인한 나비효과로 _target->_hp -= damage로 엉뚱한 메모리를 건드릴 수 있다.
k1->Attack();
return 0;
}
k2를 안전하게 삭제하는 방법
- k2를 참조하고 있는 모든 _target를 nullptr로 밀어준다.
- BUT, 이렇게 일일이 관리하기는 현실적으로 힘들다.
Smart Pointer - shared_ptr
shared_ptr
더보기
#include <iostream>
using namespace std;
#include <vector>
#include <list>
#include <deque>
#include <map>
#include <set>
#include <algorithm>
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:
int _refCount = 1;
};
template<typename T>
class SharedPtr
{
public:
SharedPtr() { } //SharedPtr를 다음과 같이 깡통으로 만들면 기본적으로 nullptr이다.
SharedPtr(T* ptr) : _ptr(ptr)
{
if (_ptr != nullptr) //관리해야할 _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--;
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, weak_ptr, unique_ptr
SharedPtr<Knight> k2; //빈 상태
{
SharedPtr<Knight> k1(new Knight());
k2 = k1; //빈 상태인 k2에 k1값을 복사하여 넣어준다. 복사대입연산자(void operator=) 사용.
}
//괄호가 끝나면 k1 소멸, BUT k1의 _refCount는 0이 아님.
return 0;
}
//k2가 소멸되면서 메모리가 소멸된다. 이 때 k1 메모리도 삭제된다.
RefCountBlock
- 참조 회수를 관리하는 블록
- _refCount는 1부터 시작하여 만약 0이되면 기억하지 않아도되어 날려도 된다는 의미다.
Smart Pointer - unique_ptr
unique_ptr
더보기
#include <iostream>
using namespace std;
#include <vector>
#include <list>
#include <deque>
#include <map>
#include <set>
#include <algorithm>
// smart pointer
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, weak_ptr, unique_ptr
shared_ptr<Knight> k1 = make_shared<Knight>();
// k1 [ ]
// k2 [ ]
{
shared_ptr<Knight> k2 = make_shared<Knight>();
k1->_target = k2;
k2->_target = k1;
}
k1->Attack();
// unique_ptr : 일반적인 복사가 막힌 포인터
unique_ptr<Knight> uptr = make_unique<Knight>();
unique_ptr<Knight> uptr2 = std::move(uptr);
return 0;
}
Shared _ptr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
#include <iostream>
using namespace std;
#include <vector>
#include <list>
#include <deque>
#include <map>
#include <set>
#include <algorithm>
// smart pointer
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;
shared_ptr<Knight> _target = nullptr;
};
class RefCountBlock
{
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()
{
// 스마트 포인터 : 포인터를 알맞는 정책에 따라 관리하는 객체 (포인터를 래핑해서 사용)
// shared _ptr, weak_ptr, unique_ptr
shared_ptr<Knight> k1 = make_shared<Knight>();
// k1 [ ]
// k2 [ ]
{
shared_ptr<Knight> k2 = make_shared<Knight>();
k1->_target = k2;
k2->_target = k1;
}
k1->Attack();
return 0;
}
|
cs |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
#include <iostream>
using namespace std;
#include <vector>
#include <list>
#include <deque>
#include <map>
#include <set>
#include <algorithm>
// smart pointer
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, weak_ptr, unique_ptr
shared_ptr<Knight> k1 = make_shared<Knight>();
// k1 [ ]
// k2 [ ]
{
shared_ptr<Knight> k2 = make_shared<Knight>();
k1->_target = k2;
k2->_target = k1;
}
k1->Attack();
// unique_ptr : 일반적인 복사가 막힌 포인터
unique_ptr<Knight> uptr = make_unique<Knight>();
unique_ptr<Knight> uptr2 = std::move(uptr);
return 0;
}
|
cs |
'⭐ Programming > C++' 카테고리의 다른 글
callback 함수 (0) | 2023.09.18 |
---|---|
[C++]L-value와 R-value, R-value reference (0) | 2022.04.24 |
[C++] 콜백 함수 (Callback function) (0) | 2022.04.17 |
[C++] 템플릿(Template) 2: 클래스 템플릿 (0) | 2022.04.17 |
[C++] 템플릿(Template) 1: 함수 템플릿 (0) | 2022.04.16 |
댓글
이 글 공유하기
다른 글
-
callback 함수
callback 함수
2023.09.18 -
[C++]L-value와 R-value, R-value reference
[C++]L-value와 R-value, R-value reference
2022.04.24 -
[C++] 콜백 함수 (Callback function)
[C++] 콜백 함수 (Callback function)
2022.04.17 -
[C++] 템플릿(Template) 2: 클래스 템플릿
[C++] 템플릿(Template) 2: 클래스 템플릿
2022.04.17