c++智能指针 shared_ptr weak_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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <assert.h>
#include "gtest/gtest.h"
<typename T>
class Unique_ptr
{
public:
explicit Unique_ptr(T *raw)
: raw_ptr_(raw)
{}
Unique_ptr(const Unique_ptr &) = delete;
Unique_ptr &operator=(const Unique_ptr &) = delete;
Unique_ptr(Unique_ptr &&rhs)
: raw_ptr_(rhs.raw_ptr_)
{
rhs.raw_ptr_ = nullptr;
}
Unique_ptr &operator=(Unique_ptr &&rhs)
{
if(this != &rhs)
{
reset(rhs.raw_ptr_);
rhs.raw_ptr_ = nullptr;
}
return *this;
}
~Unique_ptr()
{
if(raw_ptr_)
delete raw_ptr_;
}
void reset(T *raw = nullptr)
{
if(raw_ptr_)
delete raw_ptr_;
raw_ptr_ = raw;
}
T *release()
{
T *temp = raw_ptr_;
raw_ptr_ = nullptr;
return temp;
}
T &operator *()
{
assert(raw_ptr_ != nullptr);
return *raw_ptr_;
}
T *operator->()
{
assert(raw_ptr_ != nullptr);
return raw_ptr_;
}
private:
T *raw_ptr_;
};
template <typename T, typename ...Args>
Unique_ptr<T> Make_Unique(const Args &...rest)
{
return Unique_ptr<T>(new T(rest...));
}
class Object
{
public:
explicit Object(int id) : id_(id) { instances++; }
int operation() const { return id_; }
Object(const Object &) = delete;
Object &operator=(const Object &) = delete;
Object(Object &&rhs) = delete;
Object &operator=(Object &&rhs) = delete;
~Object() { instances
static int instances;
private:
int id_;
};
int Object::instances = 0;
TEST(UniquePtrTest, NullPointer)
{
auto pnull = Unique_ptr<Object>(nullptr);
ASSERT_EQ(0, Object::instances);
}
TEST(UniquePtrTest, AutoRelease)
{
{
auto pobj1 = Unique_ptr<Object>(new Object(3));
ASSERT_EQ(1, Object::instances);
}
ASSERT_EQ(0, Object::instances);
}
TEST(UniquePtrTest, MoveCopy)
{
auto pobj1 = Unique_ptr<Object>(new Object(3));
auto pobj2(std::move(pobj1));
ASSERT_EQ(1, Object::instances);
}
TEST(UniquePtrTest, MoveOperator)
{
auto pobj1 = Unique_ptr<Object>(new Object(3));
auto pobj2 = std::move(pobj1);
ASSERT_EQ(1, Object::instances);
}
TEST(UniquePtrTest, Reset)
{
auto pobj1 = Unique_ptr<Object>(new Object(3));
pobj1.reset();
ASSERT_EQ(0, Object::instances);
pobj1.reset(new Object(1));
ASSERT_EQ(1, Object::instances);
}
TEST(UniquePtrTest, Release)
{
auto pobj1 = Unique_ptr<Object>(new Object(3));
Object *p = pobj1.release();
ASSERT_EQ(1, Object::instances);
ASSERT_EQ(3, p->operation());
delete p;
}
TEST(UniquePtrTest, Operator)
{
auto pobj1 = Unique_ptr<Object>(new Object(3));
ASSERT_EQ(3, (*pobj1).operation());
ASSERT_EQ(3, pobj1->operation());
}
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

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
115
116
117
118
#include <assert.h>
#include "gtest/gtest.h"
<typename T>
class Shared_ptr
{
public:
explicit Shared_ptr(T *raw)
: raw_ptr_(raw)
{
if(raw_ptr_)
users_ = new int(1);
else
users_ = new int(0);
}
//注意这里一定是浅拷贝
Shared_ptr(const Shared_ptr &rhs)
{
shallow_copy(rhs);
}
Shared_ptr &operator=(const Shared_ptr &rhs)
{
if(this != &rhs)
{
checkIsLast();
shallow_copy(rhs);
}
return *this;
}
~Shared_ptr()
{
checkIsLast();
}
int use_count() const
{
return users_ == nullptr ? 0 : *users_;
}
T &operator*()
{
assert(raw_ptr_ != nullptr);
return *raw_ptr_;
}
T *operator->()
{
assert(raw_ptr_ != nullptr);
return raw_ptr_;
}
private:
void shallow_copy(const Shared_ptr &rhs)
{
raw_ptr_ = rhs.raw_ptr_;
users_ = rhs.users_;
++(*users_);
}
void checkIsLast()
{
if(--(*users_) == 0)
{
delete raw_ptr_;
raw_ptr_ = nullptr;
delete users_;
users_ = nullptr;
}
}
T *raw_ptr_;
int *users_;
};
TEST(SharedPtrTest, NullPointer)
{
auto pnull = Shared_ptr<Object>(nullptr);
ASSERT_EQ(0, Object::instances);
}
TEST(SharedPtrTest, AutoRelease)
{
{
auto pobj1 = Shared_ptr<Object>(new Object(3));
ASSERT_EQ(1, Object::instances);
ASSERT_EQ(1, pobj1.use_count());
}
ASSERT_EQ(0, Object::instances);
}
TEST(SharedPtrTest, CopyCtr)
{
{
auto pobj1 = Shared_ptr<Object>(new Object(3));
auto pobj2(pobj1);
ASSERT_EQ(1, Object::instances);
ASSERT_EQ(2, pobj2.use_count());
}
ASSERT_EQ(0, Object::instances);
}
TEST(SharedPtrTest, Assignment)
{
{
auto pobj1 = Shared_ptr<Object>(new Object(3));
auto pobj2 = Shared_ptr<Object>(new Object(4));
ASSERT_EQ(2, Object::instances);
ASSERT_EQ(1, pobj1.use_count());
ASSERT_EQ(1, pobj2.use_count());
pobj1 = pobj2;
ASSERT_EQ(1, Object::instances);
ASSERT_EQ(2, pobj1.use_count());
ASSERT_EQ(2, pobj2.use_count());
ASSERT_EQ(4, pobj1->operation());
}
ASSERT_EQ(0, Object::instances);
}
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

weak_ptr

待续