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. C# 跨线程调用控件的4中方法

    原文:C# 跨线程调用控件 在C# 的应用程序开发中, 我们经常要把UI线程和工作线程分开,防止界面停止响应.  同时我们又需要在工作线程中更新UI界面上的控件, 下面介绍几种常用的方法 阅读目录 线 ...

  2. React中异步模块api React.lazy和React.Suspense

    React.lazy React.lazy 这个函数需要动态调用 import().它必须返回一个 Promise,该 Promise 需要 resolve 一个 defalut export 的 R ...

  3. TensorFlow学习——入门篇

    本文主要通过一个简单的 Demo 介绍 TensorFlow 初级 API 的使用方法,因为自己也是初学者,因此本文的目的主要是引导刚接触 TensorFlow 或者 机器学习的同学,能够从第一步开始 ...

  4. quotaon - 开启关闭文件系统配额

    总览 (SYNOPSIS) quotaon [ -e | d ] [ -vug ] filesystem... quotaon [ -e | d ] [ -avug ] quotaoff [ -e | ...

  5. I2C走线技巧

  6. Django组件——Cookie与session相关

    一,会话跟踪技术 1 什么是会话跟踪技术我们需要先了解一下什么是会话!可以把会话理解为客户端与服务器之间的一次会晤,在一次会晤中可能会包含多次请求和响应.例如你给10086打个电话,你就是客户端,而1 ...

  7. pyc文件是什么

    pyc 是一种二进制文件,是由 py 文件经过编译后,生成的文件,是一种 bytecode,py 文件变成 pyc 文件后,加载的速度有所提高,而且 pyc 是一种跨平台的字节码,是由 Python ...

  8. hibernate Criteria(条件查询接口)

    Criteria(条件查询接口) // 1.简单查询 List<Customer> list = session.createCriteria(Customer.class).list() ...

  9. Struts2之param标签的使用

    struts2的s:param标签主要有两个属性name与value: 传值 若想在value属性中输入字符串,则可以这样写:<s:param name="tableTitle&quo ...

  10. SpringBoot+Shiro学习(七):Filter过滤器管理

    SpringBoot+Shiro学习(七):Filter过滤器管理 Hiwayz 关注  0.5 2018.09.06 19:09* 字数 1070 阅读 5922评论 1喜欢 20 先从我们写的一个 ...