1,智能指针本质上是一个对象,这个对象可以像原生的指针一样使用,因为智能指 针相关的类通过重载的技术将指针相关的操作符都进行了重载,所以智能指针对象可以像原生指针一样操作,今天学习智能指针类模板,通过这个类模板就可以淘汰原生的指针了;

2,智能指针的意义:

1,现代 C++ 开发库中最重要的类模板之一;

1,STL 标准库提供;

2,Qt 平台提供;

2,是 C++ 中自动内存管理的主要手段;

3,能够在很大程度上避开内存相关的问题;

1,内存泄漏,测试阶段很难发现,应用程序运行很久才能够发现,一般是申请堆空间内存忘记释放造成的;

2,多次指针释放,结果也是不确定的,有可能程序马上死掉,有可能过一段时间死掉并且这是就无法找问题究竟出在哪一行代码上;

3,STL 中的智能指针 auto_ptr:

1,生命周期结束时,销毁指向的内存空间;

1,智能指针是一个对象,有生命周期,这个特点解决内存泄漏问题;

2,不能指向堆数组,只能指向堆对象(变量);

1,这是一个缺点,但是另一个角度来看,使用堆空间的数组可以使用其他的类,比如上节课中的 HeapArray 类;

3,一片堆空间只属于一个智能指针对象;

1,避免多次释放同一个指针;

4,多个智能指针对象不能指向同一片堆空间;

1,同上面一点;

4,auto_ptr 使用初探:

1,main.cpp 文件:

 #include <iostream>
#include <string>
#include <memory> // 智能指针类模板头文件所在头文件; using namespace std; class Test
{
string m_name;
public:
Test(const char* name)
{
cout << "Hello, " << name << "." << endl; m_name = name;
} void print()
{
cout << "I'm " << m_name << "." << endl;
} ~Test()
{
cout << "Goodbye, " << m_name << "." << endl;
}
}; int main()
{
auto_ptr<Test> pt(new Test("D.T.Software")); cout << "pt = " << pt.get() << endl; pt->print(); cout << endl; auto_ptr<Test> pt1(pt); // pt 转移了对堆空间的控制权,指向 NULL; cout << "pt = " << pt.get() << endl;
cout << "pt1 = " << pt1.get() << endl; pt1->print(); return ;
}

 2,输出结果:

 Hello, D.T.Software.
pt = 0x877c008
I'm D.T.Software. pt =
pt1 = 0x877c008
I'm D.T.Software.
Goodbye, D.T.Software.

5,STL 中的其它智能指针:

1,shared_ptr:

1,带有引用计数机制,支持多个指针对象指向同一片内存;

2,weak_ptr:

1,配合 shared_ptr 而引入的一种智能指针;

3,unique_ptr:

1,一个指针对象指向一片内存空间,不能拷贝构造和赋值;

2,auto_ptr 的进化版,不能进行控制权的转移,通过不能拷贝构造和赋值实现;

6,Qt 中的智能指针:

1,QPointer:

1,当其指向的对象被销毁(释放)时,它会被自动置空;

1,可以使用多个 QPointer 智能指针指向同一个对象,当这个对象被销毁的时候,所有的智能指针对象都变为空,这可以避免多次释放和野指针的问题,非常好;

2,析构时不会自动销毁所指向的对象;

1,也就是当 QPointer 对象生命周期完结的时候,不会自动销毁堆空间中的对象,需要手动销毁;

2,这个是它的缺点,以后编程要注意这一点和其它智能指针不同;

2,QSharedPointer(和 STL 中的同名指针类模板相似):

1,引用计数型智能指针;

1,引用计数的对象是堆空间申请的对象;

2,可以被自动第拷贝和赋值;

3,当引用计数为 0 时才删除指向的对象;

1,这个智能指针对象生命周期结束后,引用计数减一;

3,Qt 还要提供自己的智能指针是和它的架构开发思想相关,因为 Qt 有自己的内存管理思想,但是这些思想并没有在 STL 中实现,所以说为了将这种内存管理思想贯彻到 Qt 中的方方面面,所以 Qt 才开发了自己的智能指针类模板,最常用和最具代表性的就是上面两类;

7,Qt 中的智能指针编程实验:

1,main.cpp 文件:

 #include <QPointer>
#include <QSharedPointer>
#include <QDebug> class Test : public QObject // Qt 开发中都要将类继承自 QObject;
{
QString m_name;
public:
Test(const char* name)
{
qDebug() << "Hello, " << name << "."; m_name = name;
} void print()
{
qDebug() << "I'm " << m_name << ".";
} ~Test()
{
qDebug() << "Goodbye, " << m_name << ".";
}
}; int main()
{
QPointer<Test> pt(new Test("D.T.Software"));
QPointer<Test> pt1(pt);
QPointer<Test> pt2(pt); pt->print();
pt1->print();
pt2->print(); delete pt; // 手工删除,这里只用删除一次就可,上述三个指针都指向NULL; qDebug() << "pt = " << pt; // QObject(0x0)
qDebug() << "pt1 = " << pt1; // QObject(0x0)
qDebug() << "pt2 = " << pt2; // QObject(0x0) qDebug() << endl; QSharedPointer<Test> spt(new Test("Delphi Tang")); // 引用计数是相对于 Text("Delphi Tang") 对象而言;
QSharedPointer<Test> spt1(spt);
QSharedPointer<Test> spt2(spt); spt->print();
spt1->print();
spt2->print(); return ;
}

 2,输出结果:

 Hello, D.T.Software.
I'm "D.T.Software".
I'm "D.T.Software".
I'm "D.T.Software".
Goodbye, "D.T.Software".
pt = QObject(0x0)
pt1 = QObject(0x0)
pt2 = QObject(0x0) Hello, D.T.Software.
I'm "D.T.Software".
I'm "D.T.Software".
I'm "D.T.Software".
Goodbye, "D.T.Software".

8,Qt 中的其它智能指针:

1,QweakPointer;

2,QScopedPointer;

3,QScopedArrayPointer;

4,QSharedDataPointer;

5,QExplicitlySharedDataPointer;

9,创建智能指针类模板编程实验:

1,SmartPointer.h 文件:

 #ifndef _SMARTPOINTER_H_
#define _SMARTPOINTER_H_ template
< typename T >
class SmartPointer
{
T* mp;
public:
SmartPointer(T* p = NULL)
{
mp = p;
} SmartPointer(const SmartPointer<T>& obj)
{
mp = obj.mp;
const_cast<SmartPointer<T>&>(obj).mp = NULL;
} SmartPointer<T>& operator = (const SmartPointer<T>& obj)
{
if( this != &obj )
{
delete mp;
mp = obj.mp;
const_cast<SmartPointer<T>&>(obj).mp = NULL;
} return *this;
} T* operator -> ()
{
return mp;
} T& operator * ()
{
return *mp;
} bool isNull()
{
return (mp == NULL);
} T* get()
{
return mp;
} ~SmartPointer()
{
delete mp;
}
}; #endif

 2,main.cpp 文件:

 #include <iostream>
#include <string>
#include "SmartPointer.h" using namespace std; class Test
{
string m_name;
public:
Test(const char* name)
{
cout << "Hello, " << name << "." << endl; m_name = name;
} void print()
{
cout << "I'm " << m_name << "." << endl;
} ~Test()
{
cout << "Goodbye, " << m_name << "." << endl;
}
}; int main()
{
SmartPointer<Test> pt(new Test("D.T.Software")); cout << "pt = " << pt.get() << endl; pt->print(); cout << endl; SmartPointer<Test> pt1(pt); cout << "pt = " << pt.get() << endl;
cout << "pt1 = " << pt1.get() << endl; pt1->print(); return ;
}

 3,输出结果:

 Hello, D.T.Software.
pt = 0x9881008
I'm D.T.Software. pt =
pt1 = 0x9881008
I'm D.T.Software.
Goodbye, D.T.Software.

4,参照了 auto_ptr 的设计,也会发生堆空间控制权的转移,发生在拷贝构造函数和符赋值操作符中;

10,小结:

1,智能指针 C++ 中自动内存管理的主要手段;

2,智能指针在各种平台上都有不同的表现形式;

1,以类模板方式出现;

3,智能指针能够尽可能的避开内存相关的问题;

1,内存泄漏;

2,多次释放;

4,STL 和 Qt 中都提供了对智能指针的支持;

C++中的智能指针类模板的更多相关文章

  1. 智能指针类模板(上)——STL中的智能指针

    智能指针类模板智能指针本质上就是一个对象,它可以像原生指针那样来使用. 智能指针的意义-现代C++开发库中最重要的类模板之一-C++中自动内存管理的主要手段-能够在很大程度上避开内存相关的问题 1.内 ...

  2. 智能指针类模板(中)——Qt中的智能指针

    Qt中的智能指针-QPointer .当其指向的对象被销毁时,它会被自动置空 .析构时不会自动销毁所指向的对象-QSharedPointer .引用计数型智能指针 .可以被自由的拷贝和赋值 .当引用计 ...

  3. OSG中的智能指针

    在OpenSceneGraph中,智能指针(Smart pointer)的概念指的是一种类的模板,它针对某一特定类型的对象(即Referenced类及其派生类)构建,提供了自己的管理模式,以避免因为用 ...

  4. ATL和vc++中的智能指针(分别是CComPtr和_com_ptr_t)

    一.智能指针的概念 智能指针是一个类,不是指针,智能指针在所包含的指针不再被使用时候会自动释放该所包含指针所占用的系统资源,而不用手动释放. 原理:智能指针封装了包含指针的AddRef()函数和Rel ...

  5. 标准库中的智能指针shared_ptr

    智能指针的出现是为了能够更加方便的解决动态内存的管理问题.注:曾经记得有本书上说可以通过vector来实现动态分配的内存的自动管理,但是经过试验,在gcc4.8.5下是不行的.这个是容易理解的,vec ...

  6. C++ 中的智能指针-基础

    简介 在现代 C++ 编程中,标准库包含了智能指针(Smart pointers). 智能指针用来确保程序不会出现内存和资源的泄漏,并且是"异常安全"(exception-safe ...

  7. C++中的智能指针

    一.动态内存管理 通常我们创建动态内存的时候,需要自己管理好内存,也就是说,new出来的对象一定要注意释放掉.下面通过例子可以看到这个问题所在: struct BBE{ int X; int Y; v ...

  8. Boost中的智能指针(转)

    这篇文章主要介绍 boost中的智能指针的使用.(转自:http://www.cnblogs.com/sld666666/archive/2010/12/16/1908265.html) 内存管理是一 ...

  9. C++中的智能指针、轻量级指针、强弱指针学习笔记

    一.智能指针学习总结 1.一个非const引用无法指向一个临时变量,但是const引用是可以的! 2.C++中的delete和C中的free()类似,delete NULL不会报"doubl ...

随机推荐

  1. SqlServer 查看表注释

    SELECT DISTINCT d.name, f.value FROM syscolumns a LEFT JOIN systypes b ON a.xusertype= b.xusertype I ...

  2. Redis设计与实现 -- 链表与字典

    1. 链表 1.1 链表的结构 在 Redis 中,链表的实现是双向链表,除此之外与常规的链表不同的是它还有三个函数指针,dup 函数用于复制链表节点所保存的值,free 函数用于释放链表节点保存的值 ...

  3. VisualVM监控远程主机

    参考博客 https://blog.csdn.net/u010004317/article/details/82948040 https://blog.csdn.net/lienfeng6/artic ...

  4. 《Redis深度历险:核心原理和应用实践》学习笔记一

    1.redis五种数据结构 1.1 String字符串类型,对应java字符串类型 用户信息序列化后,可以用string类型存入redis中批量读写string类型,见效网络消耗数字类型的string ...

  5. Sass--传多个参数

    Sass 混合宏除了能传一个参数之外,还可以传多个参数,如: @mixin center($width, $height) { width: $width; height: $height; posi ...

  6. .net core 添加NLog

    依赖项——右键——管理NuGet程序包——浏览——输入以下内容 Install-Package NLog.Extensions.Logging -Pre 在根目录下添加nlog.config   更改 ...

  7. UVA11540 Sultan's Chandelier Burnside 引理 + DP

    题目传送门 https://vjudge.net/problem/UVA-11540 https://uva.onlinejudge.org/index.php?option=com_onlineju ...

  8. Codeforces 958C3 - Encryption (hard) 区间dp+抽屉原理

    转自:http://www.cnblogs.com/widsom/p/8863005.html 题目大意: 比起Encryption 中级版,把n的范围扩大到 500000,k,p范围都在100以内, ...

  9. GET和POST是HTTP请求的两种基本方法,区别是什么!?

    GET和POST是HTTP请求的两种基本方法,要说它们的区别,接触过WEB开发的人都能说出一二. 最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数. 你可能自己 ...

  10. Python 递归算法指归

    1. 递归概述 递归( recursion)是一种编程技巧,某些情况下,甚至是无可替代的技巧.递归可以大幅简化代码,看起来非常简洁,但递归设计却非常抽象,不容易掌握.通常,我们都是自上而下的思考问题, ...