实现一个简单的 shared_ptr

RAII

Resource Acquisition Is Initialization,资源获取即初始化。以类对象的形式管理资源,结合类对象的生命周期控制资源的获取和释放,构造时获取资源析构时释放资源。C++ 保证栈对象离开作用域时总会被正确析构,所以在构造时获取的资源总能被正确释放。

代码

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
template <typename T>
class MySharedPtr {

public:

// 注意这里的参数不能为 const T*,因为 rawPtr 是非 const,不能接收一个 const 的赋值
MySharedPtr(T* _rawPtr = nullptr) : rawPtr(_rawPtr), counter(new int(1)) {}

MySharedPtr(const MySharedPtr<T>& source) : rawPtr(source.rawPtr), counter(source.counter) {
increase();
}

~MySharedPtr() {
decrease();
}

MySharedPtr& operator=(const MySharedPtr<T>& source) {
if(this == &source) return *this;
decrease(); // 自己现在要更改指向了, 释放管理的旧资源
rawPtr = source.rawPtr;
counter = source.counter;
increase();
return *this;
}

T& operator*() {
return *rawPtr;
}

T* operator->() {
return rawPtr;
}

int getCount() {
return *counter;
}

private:

T* rawPtr;
int* counter; // 所有指向 rawPtr 的智能指针共享一份 counter

void increase() {
if(counter) ++(*counter);
}

void decrease() {
if(--(*counter) == 0) {
delete rawPtr;
delete counter;
}
}

};

待完善 增加自定义释放

C++ 中的 shared_ptr 支持在初始化时指定析构方式(默认是释放指针),shared_ptr 也可以用来管理其他资源比如一个数据库连接,析构函数中应该释放此连接,此时就应该自定义该 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
template <typename T>
class MySharedPtr {

public:

// 释放器的默认值是 delete 指针
MySharedPtr(T* _rawPtr = nullptr, void (*_release)(T* pointer) = [](T* pointer){delete pointer;}) : rawPtr(_rawPtr), counter(new int(1)) {
release = _release;
}

MySharedPtr(const MySharedPtr<T>& source) : rawPtr(source.rawPtr), counter(source.counter) {
increase();
}

~MySharedPtr() {
decrease();
}

MySharedPtr& operator=(const MySharedPtr<T>& source) {
if(this == &source) return *this;
decrease(); // 自己现在要更改指向了, 释放管理的旧资源
rawPtr = source.rawPtr;
counter = source.counter;
increase();
return *this;
}

T& operator*() {
return *rawPtr;
}

T* operator->() {
return rawPtr;
}

int getCount() {
return *counter;
}

private:

T* rawPtr;
int* counter; // 所有指向 rawPtr 的智能指针共享一份 counter
void (*release)(T* pointer); // 保存构造时传入的释放方式

void increase() {
if(counter) ++(*counter);
}

void decrease() {
if(--(*counter) == 0) {
release(rawPtr); // 调用用户自定义的释放器
delete counter;
}
}

};

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!