C++中的智能指针类模板
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++中的智能指针类模板的更多相关文章
- 智能指针类模板(上)——STL中的智能指针
智能指针类模板智能指针本质上就是一个对象,它可以像原生指针那样来使用. 智能指针的意义-现代C++开发库中最重要的类模板之一-C++中自动内存管理的主要手段-能够在很大程度上避开内存相关的问题 1.内 ...
- 智能指针类模板(中)——Qt中的智能指针
Qt中的智能指针-QPointer .当其指向的对象被销毁时,它会被自动置空 .析构时不会自动销毁所指向的对象-QSharedPointer .引用计数型智能指针 .可以被自由的拷贝和赋值 .当引用计 ...
- OSG中的智能指针
在OpenSceneGraph中,智能指针(Smart pointer)的概念指的是一种类的模板,它针对某一特定类型的对象(即Referenced类及其派生类)构建,提供了自己的管理模式,以避免因为用 ...
- ATL和vc++中的智能指针(分别是CComPtr和_com_ptr_t)
一.智能指针的概念 智能指针是一个类,不是指针,智能指针在所包含的指针不再被使用时候会自动释放该所包含指针所占用的系统资源,而不用手动释放. 原理:智能指针封装了包含指针的AddRef()函数和Rel ...
- 标准库中的智能指针shared_ptr
智能指针的出现是为了能够更加方便的解决动态内存的管理问题.注:曾经记得有本书上说可以通过vector来实现动态分配的内存的自动管理,但是经过试验,在gcc4.8.5下是不行的.这个是容易理解的,vec ...
- C++ 中的智能指针-基础
简介 在现代 C++ 编程中,标准库包含了智能指针(Smart pointers). 智能指针用来确保程序不会出现内存和资源的泄漏,并且是"异常安全"(exception-safe ...
- C++中的智能指针
一.动态内存管理 通常我们创建动态内存的时候,需要自己管理好内存,也就是说,new出来的对象一定要注意释放掉.下面通过例子可以看到这个问题所在: struct BBE{ int X; int Y; v ...
- Boost中的智能指针(转)
这篇文章主要介绍 boost中的智能指针的使用.(转自:http://www.cnblogs.com/sld666666/archive/2010/12/16/1908265.html) 内存管理是一 ...
- C++中的智能指针、轻量级指针、强弱指针学习笔记
一.智能指针学习总结 1.一个非const引用无法指向一个临时变量,但是const引用是可以的! 2.C++中的delete和C中的free()类似,delete NULL不会报"doubl ...
随机推荐
- emit写了个实体转换程序
就我自己知道的,automapper是常用的,还是比较合适好用.不过我一般采用MVVM模式,其实就是简单的model名称不同而已,而这些转换器升级,扩展的很多,功能丰富,但是我用不到啊,又不能按照自己 ...
- Freeswitch Tutorial
I. Install Freeswitch 1) FreeSWITCH Explained https://freeswitch.org/confluence/ https://freeswitch. ...
- linux篇—Nginx反向代理负载均衡
一.环境准备 反向代理功能架构 3台web服务器,组建出web服务器集群 web01 10.0.0.7 172.16.1.7 web02 10.0.0.8 172.16.1.8 web03 10.0. ...
- python常用函数 S
slice(int,int) 切片,可以为切片命名增加可读性. 例子: sorted(iterable, key) 排序,支持传入参数,例如通过itemgetter传入参数(itemgetter可以传 ...
- python常用函数 O
OrderedDict() 保持dict元素插入顺序. 例子: open(path) 可以对文件进行操作,有'r'读模式.'w'写模式.'a'追加模式.'b'二进制模式.'+'读/写模式等,操作完需要 ...
- 《x的奇幻之旅》:有趣的数学科普
本书是相对比较少见的数学方面的科普书.从最简单的阿拉伯数字.加减法,一直到概率统计.微积分.群论.拓扑.微分几何,每个主题都用几千字做一些深入浅出的介绍.写的相当的有趣. 在书中又一次看到这个有趣的事 ...
- vscode舒适的字体风格
首选项-->设置-->输入setting.json-->查找到设置文件 添加如下配置 "editor.tabSize": 2, "files.assoc ...
- 前端每日实战:65# 视频演示如何用纯 CSS 创作一个摇摇晃晃的 loader
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览.https://codepen.io/comehope/pen/oyJvpe 可交互视频 此视频是可以 ...
- Java 实现文件复制的不同方法
用不同的方法实现文件的复制 1. 通道 Channel,它是一个对象,可以通过它读取和写入数据.拿NIO与原来的I/O比较,通道就像是流.是对接操作系统底层和缓冲区的桥梁. 2. 性能比较 内存映射最 ...
- centos 6.5 关闭图形界面
图形界面的关闭分为临时关闭和永久关闭,临时关闭重启系统后恢复正常,永久关闭重启系统后图形界面仍然为关闭状态. 临时关闭 init 3 永久关闭 vi /etc/inittab 修改下面一行 id:3: ...