-
Notifications
You must be signed in to change notification settings - Fork 1
/
item20_weak_ptr.cpp
114 lines (101 loc) · 4.22 KB
/
item20_weak_ptr.cpp
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>
#include<boost/smart_ptr/shared_ptr.hpp>
#include <new>
#include <memory>
#include <unordered_map>
#include "type_name.hpp"
using namespace std;
using namespace boost;
class Widget{
public:
~Widget(){cout << "Widget destroyed" << endl;}
};
using WidgetID = int;
/*
This kind of smart pointer has to contend with a problem unknown to std::shared_ptrs: the possibility that what it points to
has been destroyed. A truly smart pointer would deal with this problem by tracking when it dangles, i.e, when the object it is
supposed to point to no longer exists. That's precisely the kind of smart pointer std::weak_ptr is.
The std::weak_ptr looks anything but smart. std::weak_ptrs can't be dereferenced, nor can they be tested for nullness.
That's because std::weak_ptr isn't a standalone smart pointer. It's an augmentation of std::shared_ptr.
*/
std::shared_ptr<const Widget> fastLoadWidget(WidgetID id){
static std::unordered_map<WidgetID, std::weak_ptr<const Widget>> cache;
auto objPtr = cache[id].lock();
if(!objPtr){
cout << "Cache miss \n";
objPtr = make_shared<Widget>();
cache[id] = objPtr;
}else{
cout << "Cache hit \n";
}
return objPtr;
}
int main(){
auto spw = std::make_shared<Widget>();
std::weak_ptr<Widget> wpw(spw);
cout << "After constructing weak pointer, the use_count of spw: " << spw.use_count() << endl;
auto spw1 = spw;
cout << "After copy assignment of shared_ptr : " << spw.use_count() << endl;
auto spw2(spw);
cout << "After copy construction, the use_count of spw : " << spw.use_count() << endl;
if(!wpw.expired()){
cout << "Weak pointer is not expired \n";
}
/* Deleting original shared_ptr is not good */
// delete(spw.get());
// delete(spw2.get());
// delete(spw1.get());
//cout << "After deleting all shared pointers, we get spw.use_count : " << spw.use_count() << endl;
/* Let's try boost */
auto sp =new boost::shared_ptr<int>(new int(2));
cout << "sp's use_count : " << sp->use_count() << endl;
delete(sp);
/* Use std::shared_ptr */
auto sp1 = make_shared<Widget>();
std::weak_ptr<Widget>wp1(sp1);
auto _sp1 = sp1;
auto sp2 = wp1.lock();
/* std::shared_ptr<T>::use_count
Returns the number of different shared_ptr instances (this included) managing the current object.
If there is no managed object, 0 is returned (for it is reset).
In multithreaded environment, the value returned by the use_count is approximate(typically implementatioins use
a memory_order_relaxed load)
*/
cout << "After locking: the use_count of sp1: " << sp1.use_count() << endl;
//std::weak_ptr<Widget> wp(sp);
cout << "Before sp1.reset() sp1.use_count() " << sp1.use_count() << endl;
sp1.reset();
cout << "After sp1.reset() sp1.use_count() " << sp1.use_count() << endl;
cout << "Before sp2.reset() sp2.use_count() " << sp2.use_count() << endl;
sp2.reset();
cout << "After sp2.reset() sp2.use_count() " << sp2.use_count() << endl;
//_sp1.reset();
cout << "Before _sp1.reset() _sp1.use_count() " << _sp1.use_count() << endl;
_sp1.reset();
cout << "After _sp1.reset() _sp1.use_count() " << _sp1.use_count() << endl;
auto sp3 = wp1.lock();
if(sp3 == nullptr){
cout << "Has been empty, you're late \n";
}
/* Construct unique_ptr with shared_ptr
Can not do it.
*/
// std::unique_ptr<Widget>up(wp1);
//cout << "Whether the weak_pointer is valid: " << wp.expired() << endl;
//cout << "After deleting sp, the valid of sp : " << wp.expired() << endl;
auto a = fastLoadWidget(1);
cout << "Something's use_count() : " << a.use_count() << endl;
auto b = fastLoadWidget(1);
cout << "Something's use_count() : " << b.use_count() << endl;
/* Cycle pointer */
auto c1 = make_shared<Widget>();
auto c2(c1);
c1 = c2;
cout << "c1's use_count() : " << c1.use_count() << endl;
cout << "c2's use_count() :" << c2.use_count() << endl;
c1.reset();
cout << "After reseting, c1's use_count() " << c1.use_count() << endl;\
c2.reset();
cout << "After reseting, c2's use_count() " << c2.use_count() << endl;
return 0;
}