c++11中的智能指针

智能指针,一个非常好用的东西,特别是 弱引用 指针用于 内存泄漏 检测非常有用,类似 c# 中的 WeakReference

下面是《深入理解C++11》中的截图

在头文件中,使用std::命名空间

img

img

img

img

以下是自己的实现,有更详细的注释

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 <stdlib.h>
#include <iostream>
#include <sstream>
#include <string>
#include <memory>

class Human
{
public:
Human() : mNum(nullptr)
{
mNum = new int(123);
printf("Human 构造\n");
}
Human(const Human& _h)
{
mNum = new int(*_h.mNum);
printf("Human 拷贝构造\n");
}
Human(Human && _h)
{
mNum = _h.mNum; //
_h.mNum = nullptr; //必须将被偷者的指针置空,不然临时对象析构时会释放内存
printf("Human 移动构造\n");
}
virtual ~Human()
{
printf("Human 析构\n");
if (mNum) delete mNum;
}
void show(){ if(mNum) printf("--- num:%d\n", *mNum); }
private:
int* mNum;
};

void testSmartPoint1()
{
std::unique_ptr<Human> up1(new Human);
//std::unique_ptr<Human> h2 = h1; //编译失败,
up1->show();

std::unique_ptr<Human> up3 = std::move(up1); //将h1对new Human的所有权交给h3,h1置空empty
up3->show(); //对象会随着最后拥有对象的唯一指针的生命周期的结束而结束

//h1->show();//运行时崩溃,h1已交出对象所有权,现在为empty状态

up3.reset();//已显式释放对象内存
//h3->show();//运行时崩溃,已显式释放对象内存,现在为empty状态
system("pause");
}

void testSmartPoint2()
{
//如果std::shared_ptr<Human> sp1为empty状态,则不会进入这样的判断if(sp1)
//void reset() _NOEXCEPT
//{ // release resource and convert to empty shared_ptr object
// shared_ptr().swap(*this);
//}
//use_count() {return (_Rep ? _Rep->_Use_count() : 0);}
/*
reset函数
是用初始化一个shared_ptr()对象(里面的_Rep和_Ptr初始化都是nullptr),
然后调用swap(T&a),实现将a的_Rep和_Ptr都置为nullptr
调用过一次后,之后所以无论调多少次reset,都是做无用功

use_count函数
判断_Rep是否nullptr,不为nullptr则返回对象的引用次数
*/
std::shared_ptr<Human> sp1(new Human());
std::shared_ptr<Human> sp2 = sp1;
std::shared_ptr<Human> sp3 = sp1;
printf("--- ref count:%ld\n", sp2.use_count());//3

sp1.reset(); //显式减少引用,_Rep和_Ptr都置为nullptr,sp1为empty状态
sp1.reset(); //做无用功
sp1.reset(); //做无用功
printf("--- sp1 ref count:%ld\n", sp1.use_count()); //0
//sp1->show(); //此时sp1为empty状态,不可以在使用sp1->show()

printf("--- sp2 ref count:%ld\n", sp2.use_count()); //2 //因为此时sp3和sp2还保持这对对象的引用,所以对象还未被释放
printf("--- sp3 ref count:%ld\n", sp3.use_count()); //2

sp2.reset();//减少引用后,_Rep和_Ptr都置为nullptr,sp2为empty状态
printf("--- sp2 ref count:%ld\n", sp2.use_count()); //0
printf("--- sp3 ref count:%ld\n", sp3.use_count()); //1 //因为此时sp3还保持这对对象的引用,所以对象还未被释放

sp3.reset();//减少引用后,_Rep和_Ptr都置为nullptr,sp3为empty状态 //此时已无shared_ptr对sp3保持引用,对象被释放
printf("--- sp3 ref count:%ld\n", sp3.use_count()); //0
system("pause");
}
/*
Human 构造
--- ref count:3
--- sp1 ref count:0
--- sp2 ref count:2
--- sp3 ref count:2
--- sp2 ref count:0
--- sp3 ref count:1
Human 析构
--- sp3 ref count:0
请按任意键继续. . .
*/

void testSmartPoint3()
{
std::shared_ptr<Human> sp1(new Human());
std::shared_ptr<Human> sp2 = sp1;
std::weak_ptr<Human> wp = sp1; //不会影响引用计数

printf("--- ref count:%ld\n", sp2.use_count());//2

sp2.reset();

printf("--- sp1 count:%ld\n", sp1.use_count());//1
std::shared_ptr<Human> sp4 = wp.lock(); //如果此时还有对对象保持引用,这行代码结束后sp4也将会保持引用,引用计数+1
if (sp4)
printf("--- sp4 ref count:%ld\n", sp4.use_count());//2


sp1.reset();
printf("--- wp ref count:%ld\n", wp.use_count());//1
if (sp4)
sp4.reset(); //这行代码后,将无std::shared_ptr对对象保持引用,对象将析构
printf("--- wp ref count:%ld\n", wp.use_count());//0

std::shared_ptr<Human> sp5 = wp.lock(); //如果此时没有对对象保持引用,则sp5是empty状态
if (sp5)
printf("--- sp5 ref count:%ld\n", sp4.use_count());

}

int main()
{
//testSmartPoint1();
//testSmartPoint2();
testSmartPoint3();

system("pause");
return 0;
}