C++ Code 
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
 
/*
    SmartPtr.cpp
    Author: Michael Joessy
    Date: 2017-06-07
    Marks: C++里面的四个智能指针: auto_ptr, shared_ptr, weak_ptr, unique_ptr;
           其中后三个是C++11支持,并且第一个已经被C++11弃用。

为什么要使用智能指针:
    我们知道C++的内存管理是让很多人头疼的事,当我们写一个new语句时,一般就会立即把delete语句直接也写了;
    但是我们不能避免程序还未执行到delete时就跳转了或者在函数中没有执行到最后的delete语句就返回了;
    如果我们不在每一个可能跳转或者返回的语句前释放资源,就会造成内存泄露。
    使用智能指针可以很大程度上的避免这个问题:
    因为智能指针就是一个类,当超出了类的作用域是,类会自动调用析构函数,析构函数会自动释放资源。
*/

#include <memory>
#include <iostream>
#include <string>

using namespace std;
using namespace std::tr1;

//auto_ptr      http://www.cplusplus.com/reference/memory/auto_ptr/
//unique_ptr    http://www.cplusplus.com/reference/memory/unique_ptr/
//share_ptr     http://www.cplusplus.com/reference/memory/share_ptr/
//weak_ptr      http://www.cplusplus.com/reference/memory/weak_ptr/
class TestSmartPtr
{
public:
    TestSmartPtr(string str)
    {
        m_str = str;
        cout << "TestSmartPtr creat\n";
    }
    ~TestSmartPtr()
    {
        cout << "TestSmartPtr delete:" << m_str <<endl;
    }
    string& getStr()
    {
        return m_str;
    }
    void setStr(string str)
    {
        m_str = str;
    }
    void print()
    {
        cout << m_str << endl;
    }
private:
    string m_str;
};

class classB;
class classA
{
public:
    //shared_ptr<classB> pB_;
    weak_ptr<classB> pB_;
    ~classA()
    {
        cout << "classA delete\n";
    }
};
class classB
{
public:
    shared_ptr<classA> pA_;
    ~classB()
    {
        cout << "classB delete\n";
    }
};

int main(void)
{
    //auto_ptr
    /*成员函数get()返回一个原始的指针,成员函数reset()重新绑定指向的对象,而原来的对象则会被释放
      判断一个智能指针是否为空应该使用if(pTestAutoPtr.get() == NULL)
      成员函数release()只是把智能指针赋值为空,但是它原来指向的内存并没有被释放,相当于它只是释放了对资源的所有权
      当我们想要在中途释放资源,而不是等到智能指针被析构时才释放,我们可以使用pTestAutoPtr.reset(); 语句。
    */

auto_ptr<TestSmartPtr> pTestAutoPtr(new TestSmartPtr("315"));
    if(pTestAutoPtr.get() == NULL)
    {
        cout << "pTestAutoPtr = NULL\n";
    }
    pTestAutoPtr->setStr("Michael ");
    pTestAutoPtr->print();
    pTestAutoPtr.get()->print();
    pTestAutoPtr->getStr() += "Joessy !";
    (*pTestAutoPtr).print();
    pTestAutoPtr.reset(new TestSmartPtr("315"));
    pTestAutoPtr->print();
    pTestAutoPtr.release();
#endif
    //unique_ptr
    /*unique_ptr 是一个独享所有权的智能指针,它提供了严格意义上的所有权,包括:
    1、拥有它指向的对象
    2、无法进行复制构造,无法进行复制赋值操作。即无法使两个unique_ptr指向同一个对象。但是可以进行移动构造和移动赋值操作
    3、保存指向某个对象的指针,当它本身被删除释放的时候,会使用给定的删除器释放它指向的对象
    unique_ptr 可以实现如下功能:
    1、为动态申请的内存提供异常安全
    2、动态申请的内存所有权传递给某函数
    3、从某个函数返回动态申请内存的所有权
    4、在容器中保存指针
    5、auto_ptr应该具有的功能
    */

unique_ptr<int> up(p);
    unique_ptr<TestSmartPtr> pTestUniquePtr1(new TestSmartPtr("123"));
    unique_ptr<TestSmartPtr> pTestUniquePtr2(new TestSmartPtr("456"));
    pTestUniquePtr1->print();
    pTestUniquePtr2 = std::move(pTestUniquePtr1);   //不能直接pTestUniquePtr2 = pTestUniquePtr1
    if(pTestUniquePtr1 == NULL)
    {
        cout << "pTestUniquePtr1 = NULL\n";
    }
    TestSmartPtr* p = pTestUniquePtr2.release();
    p->print();
    pTestUniquePtr1.reset(p);
    pTestUniquePtr1->print();
#endif
    //share_ptr
    /* 从share中就可以看出资源可以被多个指针共享,它使用计数机制来表明资源被几个指针共享。
    可以通过成员函数use_count()来查看资源的所有者个数。
    除了可以通过new来构造,还可以通过传入auto_ptr, unique_ptr,weak_ptr来构造。
    当我们调用release()时,当前指针会释放资源所有权,计数减一。
    当计数等于0时,资源会被释放。
    */

shared_ptr<TestSmartPtr> pTestSharePtr1(new TestSmartPtr("123"));
    shared_ptr<TestSmartPtr> pTestSharePtr2(new TestSmartPtr("456"));
    cout << pTestSharePtr2->getStr()<<endl;
    cout << pTestSharePtr2.use_count()<<endl;
    pTestSharePtr1 = pTestSharePtr2;            //"456"引用次数加1,"123"销毁
    pTestSharePtr1->print();
    cout << pTestSharePtr2.use_count() << endl;
    cout << pTestSharePtr1.use_count() << endl;
    pTestSharePtr1.reset();
    pTestSharePtr2.reset();                     //此时"456"销毁
#endif
    //weak_ptr
    /*weak_ptr是用来解决shared_ptr相互引用时的死锁问题;
    如果说两个shared_ptr相互引用,那么这两个指针的引用计数永远不可能下降为0,资源永远不会释放。
    它是对对象的一种弱引用,不会增加对象的引用计数,和shared_ptr之间可以相互转化;
    shared_ptr可以直接赋值给它,它可以通过调用lock函数来获得shared_ptr。
    */

shared_ptr<classB> pB(new classB());
    shared_ptr<classA> pA(new classA());
    pB->pA_ = pA;
    pA->pB_ = pB;
    cout << pB.use_count() << endl;
    cout << pA.use_count() << endl;
#endif
    /*说明:
    pA与pB之间互相引用,两个资源的引用计数为2;
    当要跳出函数时,智能指针pA与pB析构时两个资源引用计数会减一;
    但是两者引用计数还是为1,导致跳出函数时资源没有被释放(classA与classB的析构函数没有被调用).
    
    如果把其中一个改为weak_ptr就可以了,我们把类A里面的shared_ptr<B> pB_; 改为weak_ptr<B> pb_;
    这样的话,资源classB的引用开始就只有1;
    当pB析构时,B的计数变为0,B得到释放;
    B释放的同时也会使A的计数减一;
    同时pa析构时使A的计数减一,那么A的计数为0,A得到释放。
    */

cin.get();
    ;
}

C++ 智能指针学习的更多相关文章

  1. Qt 智能指针学习(7种指针)

    Qt 智能指针学习 转载自:http://blog.csdn.net/dbzhang800/article/details/6403285 从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ ...

  2. Android 智能指针学习 一

    Android5.1 中智能指针涉及的文件如下: system/core/include/utils/RefBase.h system/core/libutils/RefBase.cpp system ...

  3. Qt 智能指针学习(7种QT的特有指针)

    从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include <QApplication> #include <QLabel> int main(int arg ...

  4. Qt 智能指针学习(7种QT智能指针和4种std智能指针)

    从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include <QApplication> #include <QLabel> int main(int arg ...

  5. Qt 智能指针学习

    原地址:http://blog.csdn.net/dbzhang800/article/details/6403285 从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include & ...

  6. [转]Qt 智能指针学习

    从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include <QApplication> #include <QLabel> int main(int arg ...

  7. c++——智能指针学习(shared_ptr和weak_ptr)

    先看一个例子:Stark和Targaryen家族你中有我,我中有你.我们设计以下类企图避免内存泄漏,使得析构函数都能调用到: #include<iostream> #include< ...

  8. c++——智能指针学习(unique_ptr)

    1.为什么会有unique_ptr? 动态内存忘记delete,导致内存泄漏.比如: p = new (); if(...) { return ; } delete p; 因此我们需要一种方式来解决这 ...

  9. [C/C++] 智能指针学习

    转自:http://blog.csdn.net/xt_xiaotian/article/details/5714477 一.简介 由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存 ...

随机推荐

  1. 35 、HashSet详解

    HashSet特点 1.不能保证元素的排列顺序 2.没有重复元素 3.HashSet不是同步的,多个线程同时访问一个HashSet,需要通过代码来保持同步 4.集合元素可以是null 当向HashSe ...

  2. 【centos6.5】安装LNMP(linux公社)

    1:查看环境: 1 2 [root@10-4-14-168 html]# cat /etc/redhat-release CentOS release 6.5 (Final) 2:关掉防火墙 1 [r ...

  3. Android上怎样使用《贝赛尔曲线》

    首先对于<赛贝尔曲线>不是很了解的童鞋,请自觉白度百科.google. 为了方便偷懒的童鞋,这里给个<贝赛尔曲线>百科地址,以及一段话简述<贝赛尔曲线>: < ...

  4. 搜狐畅游CEO王滔辞职

    凤凰科技讯 11月3日消息,搜狐公布公告确认搜狐畅游CEO离职.公告称王滔因个人原因辞去畅游首席运行官职务.将继续担任畅游公司董事和首席产品官. 据搜狐公告,董事会任命搜狐总裁余楚媛与畅游总裁陈德文为 ...

  5. numpy 文件存取 npy、npz

    转处:http://blog.csdn.net/pipisorry/article/details/39088003 NumPy提供了多种文件操作函数方便我们存取数组内容. 文件存取的格式:二进制和文 ...

  6. ubuntu下将CapsLock改为Ctrl键

    需求:Ubuntu下用Vim时,ESC因为在左上角,还算是好按,但是Ctrl就太坑了,在左右两个下角,实在是太不方便了. 经过分析决定将:CapsLock键改为Ctrl,但仍然保留下面的原Ctrl键( ...

  7. Error-Project facet Java version 1.8 is not supported

    最近导入最新的Strtus2.5.10.1 Demo时出现了这个错误 解决方案如下: 选中工程——右键——Properties 然后依次展开找到如图所示内容,将1.8改成1.7即可. 原因:工程默认配 ...

  8. 最新的Zynq资料整理

    1.Zynq修炼秘籍 基于ZYNQ的FPGA基础入门 基于ZYNQ的Soc入门基础 基于ZYNQ的裸机应用开发 基于ZYNQ硬件的LINUX开发 基于ZYNQ的HLS图像算法设计 基于ZYNQ的图像处 ...

  9. [elk]Mutate filter plugin增删改查字段

    Mutate filter plugin参考: https://www.elastic.co/guide/en/logstash/current/plugins-filters-mutate.html ...

  10. DLL编写中extern “C”和__stdcall的作用

    动态链接库的使用有两种方式,一种是显式调用.一种是隐式调用. (1)       显式调用:使用LoadLibrary载入动态链接库.使用GetProcAddress获取某函数地址. (2)      ...