0%

C++智能指针

auto_ptr

auto_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
//auto_ptr的语义实现
template<class T>
class smart_ptr//不能出现两个smart_ptr的ptr指向同一个地址,否则析构会重复delete
{
private:
T *ptr;
public:
explicit smart_ptr(T *ptr = nullptr) : ptr(ptr) {}

smart_ptr(smart_ptr &rhs)//rhs的ptr变为空
{
ptr = rhs.release();
}

smart_ptr &operator=(smart_ptr &rhs)//赋值之后rhs的ptr为空
{
if (ptr == rhs.get())return *this;//自赋值问题
smart_ptr(rhs).swap(*this);
return *this;
}

~smart_ptr()
{
delete ptr;
}

T *release()
{
T *_ptr = ptr;
ptr = nullptr;
return _ptr;
}

void swap(smart_ptr &rhs)
{
std::swap(ptr, rhs.ptr);
}

T *get() const { return ptr; }

T &operator*() const { return *ptr; };//空指针访问会报错

T *operator->() const { return ptr; }

explicit operator bool() const { return ptr; }//用于bool表达式
};

int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
smart_ptr<int> A(new int(1)), B(new int(2));
std::cout << A.get() << " " << B.get() << std::endl;
std::cout << *A << " " << *B << std::endl;
A = B;
std::cout << A.get() << " " << B.get() << std::endl;
std::cout << *A << std::endl;
A = A;
std::cout << A.get() << " " << *A << std::endl;
return 0;
}

shared_ptr

shared_ptr简单版(非线程安全)语义实现

可以使用abi::__cxa_demangle函数得到类的类型从而提高理解

默认赋值运算符为浅拷贝,刚好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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include <bits/stdc++.h>
#include <cxxabi.h>

class shape
{
public:
virtual ~shape() { std::cout << "~shape()" << std::endl; }
};

class circle : public shape
{
public:
~circle() { std::cout << "~circle()" << std::endl; }
};

class shared_count
{
private:
int cnt;
public:
shared_count() : cnt(1) {}

void add_count() { cnt++; }

int sub_count() { return --cnt; }

int use_count() const { return cnt; }
};

template<class T>
class Shared_ptr
{
private:
T *ptr;
shared_count *shared_count_ptr;
public:
explicit Shared_ptr(T *ptr = nullptr) : ptr(ptr)
{
if (ptr)
shared_count_ptr = new shared_count;
}

Shared_ptr(const Shared_ptr &rhs) : ptr(rhs.ptr)
{
if (ptr)
{
rhs.shared_count_ptr->add_count();
shared_count_ptr = rhs.shared_count_ptr;
}
}

template<class U> friend
class Shared_ptr;

template<class U>
Shared_ptr(const Shared_ptr<U> &rhs):ptr(rhs.ptr)//隐式转换情况
{
if (ptr)
{
rhs.shared_count_ptr->add_count();
shared_count_ptr = rhs.shared_count_ptr;
}
}

template<class U>
Shared_ptr(const Shared_ptr<U> &rhs, T *another_ptr):ptr(another_ptr)
{
if (ptr)
{
rhs.shared_count_ptr->add_count();
shared_count_ptr = rhs.shared_count_ptr;
}
}

template<class U>
Shared_ptr(Shared_ptr<U> &&rhs):ptr(rhs.ptr)//此处并不被编译器视为移动构造函数
{
if (ptr)
{
shared_count_ptr = rhs.shared_count_ptr;
rhs.ptr = nullptr;
}
}

~Shared_ptr()
{
if (ptr && shared_count_ptr->sub_count() == 0)
{
delete ptr;
delete shared_count_ptr;
}
}

Shared_ptr &operator=(Shared_ptr rhs) noexcept
{
rhs.swap(*this);
return *this;
}

void swap(Shared_ptr &rhs)
{
std::swap(ptr, rhs.ptr);
std::swap(shared_count_ptr, rhs.shared_count_ptr);
}

int use_count() const
{
return ptr ? shared_count_ptr->use_count() : 0;
}

T *get() const
{
return ptr;
}

T &operator*() noexcept { return *ptr; }

T *operator->() noexcept { return ptr; }

explicit operator bool() const noexcept { return ptr; }
};

template<class T>
Shared_ptr<T> swap(const Shared_ptr<T> &lhs, const Shared_ptr<T> &rhs)noexcept
{
lhs.swap(rhs);
}

template<class T, class U>
Shared_ptr<T> static_pointer_cast(const Shared_ptr<U> &rhs)
{
T *ptr = static_cast<T *>(rhs.get());
return Shared_ptr<T>(rhs, ptr);
}

template<class T, class U>
Shared_ptr<T> reinterpret_pointer_cast(const Shared_ptr<U> &rhs)
{
T *ptr = reinterpret_cast<T *>(rhs.get());
return Shared_ptr<T>(rhs, ptr);
}

template<class T, class U>
Shared_ptr<T> const_pointer_cast(const Shared_ptr<U> &rhs)
{
T *ptr = const_cast<T *>(rhs.get());
return Shared_ptr<T>(rhs, ptr);
}

template<class T, class U>
Shared_ptr<T> dynamic_pointer_cast(const Shared_ptr<U> &rhs)
{
T *ptr = dynamic_cast<T *>(rhs.get());
return Shared_ptr<T>(rhs, ptr);
}

int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
Shared_ptr<circle> p1(new circle);
std::cout << "use count of p1 = " << p1.use_count() << std::endl;
Shared_ptr<shape> p2;
std::cout << "use count of p2 = " << p2.use_count() << std::endl;
std::cout << abi::__cxa_demangle(typeid(p1).name(), 0, 0, 0) << std::endl;
p2 = p1;
std::cout << "use count of p2 = " << p2.use_count() << std::endl;
if (p1)
std::cout << "p1 is not empty" << std::endl;

Shared_ptr<circle> p4 = p1;
std::cout << "use count of p4 = " << p4.use_count() << std::endl;
p4 = p1;//注意171行调用拷贝构造函数,173行调用赋值重载运算符

Shared_ptr<circle> p3 = dynamic_pointer_cast<circle>(p2);//默认赋值运算符为浅拷贝
std::cout << "use count of p3 = " << p3.use_count() << std::endl;
return 0;
}