第九课、智能指针示例------狄泰软件学院

一、内存泄漏(臭名昭著的bug)

(1)、动态申请堆空间,用完后不归还

(2)、c++语言中没有垃圾回收机制

(3)、指针无法控制所指向的堆空间生命周期(如局部指针生命周期结束了堆空间的生命周期还未结束)

二、智能指针

1、当代c++平台的智能指针

(1)、指针生命周期结束时主动释放堆空间

(2)、一片堆空间最多只能由一个智能指针标识

(3)、杜绝指针运算和指针比较

2、智能指针的设计方案

(1)、通过类模板描述指针的行为:能够定义不同类型的指针变量

(2)、重载指针特征操作符(->和*):利用对象模拟原生指针的行为

3、下面说明用c++来实现智能指针的具体做法

1、为了达到指针生命周期结束时主动释放堆空间的目的,需要在析构函数中将指针删除

  SmartPoiter(T* p = NULL)
    {
        m_pointer = p;//开始时指向NULL
    }

    T* operator -> ()
    {
        return m_pointer;
    }

    T& operator * ()
    {
        return *m_pointer;
    }

    bool isNull()
    {
        return (m_pointer == NULL);
    }

    T* get()
    {
        return m_pointer;
    }

    ~SmartPoiter()
    {
        delete m_pointer;//析构函数中删除原生指针
    }

2、而要达到一片内存只有一个指针管理的目的,必须在拷贝构造函数和赋值操作符处做处理

  SmartPoiter(const SmartPoiter<T>& obj)
    {
        m_pointer = obj.m_pointer;
        const_cast<SmartPoiter<T>&>(obj).m_pointer = NULL;//因为obj是const属性,不能做左值,需先进行强制类型转换
    }

    SmartPoiter<T>& operator = (const SmartPoiter<T>& obj)
    {
        if( this != &obj )
        {
            delete m_pointer;
            m_pointer = obj.m_pointer;
            const_cast<SmartPoiter<T>&>(obj).m_pointer = NULL;
        }

        return *this;
    }

3、而要实现不能进行指针运算和指针比较则非常容易:不重载相应的操作符即可(如不重载++操作符和==操作符等)

三、完整代码

#ifndef SMARTPOINTER_H
#define SMARTPOINTER_H

namespace DTLib
{
template <typename T>
class SmartPoiter
{
protected:
    T* m_pointer;
public:
    SmartPoiter(T* p = NULL)
    {
        m_pointer = p;
    }

    SmartPoiter(const SmartPoiter<T>& obj)
    {
        m_pointer = obj.m_pointer;
        const_cast<SmartPoiter<T>&>(obj).m_pointer = NULL;
    }

    SmartPoiter<T>& operator = (const SmartPoiter<T>& obj)
    {
        if( this != &obj )
        {
            delete m_pointer;
            m_pointer = obj.m_pointer;
            const_cast<SmartPoiter<T>&>(obj).m_pointer = NULL;
        }

        return *this;
    }

    T* operator -> ()
    {
        return m_pointer;
    }

    T& operator * ()
    {
        return *m_pointer;
    }

    bool isNull()
    {
        return (m_pointer == NULL);
    }

    T* get()
    {
        return m_pointer;
    }

    ~SmartPoiter()
    {
        delete m_pointer;
    }
};
}

#endif // SMARTPOINTER_H

SmartPointer.h

#include <iostream>
#include "SmartPointer.h"

using namespace std;
using namespace DTLib;

class Test
{
public:
    Test()
    {
        cout << "Test()" << endl;
    }

    ~Test()
    {
        cout << "~Test" << endl;
    }
};

int main()
{
    SmartPoiter<Test> p1 = new Test();
    //SmartPoiter<Test> p2 = p1;
    SmartPoiter<Test> p2;
    p2 = p1;

    cout << "p1=" << p1.isNull() << endl;
    cout << "p2=" << p2.isNull() << endl;

    //p1++;//不能进行指针运算,因为没有重载相应的操作符
    return 0;
}

注:智能指针使用军规:只能用来指向堆空间的单个对象或者单个变量

四、小结

(1)、指针操作符(->和*)可以被重载

(2)、重载指针特征操作符能够使用对象代替指针

(3)、智能指针只能用于指向堆空间中的内存

(4)、智能指针的意义在于最大程度避免内存问题

 

时间: 2024-09-30 23:52:41

第九课、智能指针示例------狄泰软件学院的相关文章

数据结构第六课------------狄泰软件学院

图片出自狄泰软件学院工程里面一般采用时间复杂度在 O(n^3) 之前的算法.算法的最好与最坏情况:一般推断算法的最坏情况,当程序在最坏情况都能满足要求是,说明在最好和平均情况都能满足要求. 算法的空间复杂度 (Space Complexity)定义:S(n) = S(f(n))n为算法的问题规模f(n)为空间使用函数,与n有关推导时间复杂度的方法同样适用于空间复杂度如当算法所需要的空间复杂度是常数时,空间复杂度为S(1)S(n+4) = S(n)空间与时间的比较(1)多数情况下,算法的时间复杂度

第十三课、类族的结构进化-------------------狄泰软件学院

一.遵循经典设计原则 DTLib中的所有类位于单一继承树 IvalidOperationEXception是新增的异常类,描述某些成员函数在状态不对的时候被抛出 二.改进的关键点 1.EXception类继承自Object类:堆空间中创建异常对象失败时,返回NULL指针,用的是自己的new版本 更改: 2.新增IvalidOperationEXception异常类:成员函数调用时,如果状态不正确则抛出该异常 增加: //非法操作异常 class IvalidOperationEXception:

第37课 智能指针分析

1. 永恒的话题:内存泄漏 (1)动态申请堆空间,用完后不归还 (2)C++语言中没有垃圾回收的机制 (3)指针无法控制所指堆空间的生命周期 [编程实验]内存泄漏 #include <iostream> #include "IntArray.h" using namespace std; class Test { int i; public: Test(int i) { this->i = i; cout << "Test(int i)"

第61课 智能指针类模板

1. 智能指针的意义 (1)现代C++开发库中最重要的类模板之一 (2)C++中自动内存管理的主要手段 (3)能够在很大程度上避开内存相关的问题(如内存泄漏.内存的多次释放等) 2. STL中的智能指针 (1)auto_ptr智能指针 ①生命周期结束时,销毁指向的内存空间 ②只能用来管理单个动态创建的对象,而不能管理动态创建的数组.即不能指向堆数组,只能指针堆对象(变量) int* pn = new int[100]; auto_ptr<int> ap(pn); //auto_ptr指向堆数组

智能指针示例

智能指针实际上就是通过模板技术实现的一个类 内存泄露(臭名昭著的Bug)——在软件开发和测试阶段都不容易被发现-动态申请堆空间,用完后不归还-C++语言中没有垃圾回收的机制-指针无法控制所指堆空间的生命周期 当代C++软件平台中的智能指针-指针生命周期结束时主动释放堆空间-一片堆空间最多只能由一个指针标识 -杜绝指针运算和指针比较 智能指针的设计方案-通过类模板描述指针的行为 能够定义不同类型的指针对象-重载指针特征操作符(->和*) 利用对象模拟原生指针的行为 SmartPointer.h #

第十六课、顺序存储结构的抽象实现----------狄泰软件学院

一.课程目标 1.完成顺序存储结构的抽象实现,既然是抽象实现,自然就是抽象类,不能生成对象 (1).抽象类模板,存储空间的位置和大小由子类完成  (2).这里只实现顺序存储结构的关键操作(增.删.查等) (3).提供数组操作符,方便快速获取元素(要提供const版本的,方便const对象调用) 二.具体实现 这里需注意几点 (1).这里将capacity()函数设置为纯虚函数,说明在这里还不需要实现它,将其留到子类中在实现. (2).数组操作符的返回值一个是引用一个是值,是因为const对象不能

第十四课、线性表的本质和操作-----------------狄泰软件学院

一.线性表(List)的表现形式 1.零个或者多个数据元素组成的集合 2.数据元素在位置上是有序排列的 3.数据元素的个数是有限的 4.数据元素的类型必须相同 二.线性表(List)的抽象定义 1.线性表是具有相同类型的n(>=0)个数据元素的有限序列 {a0,a1,a2,....an-1} ai是表项(数据元素),n是表长度 三.线性表(List)的性质 1.a0为线性表的第一个元素,只有一个后继 2.an-1为线性表的最后一个元素,只有一个前驱 3.除a0和an-1外的其它元素ai,既有前驱

第五十八课、自定义模型类(上)------------------狄泰软件学院

 一.自定义模型类 1.QStandardItemModel是一个通用的模型类 (1).能够以任意的方式组织数据(线程.非线性) (2).数据组织的基本单位为数据项(QStandardItem) (3).每一个数据项能够存储多个具体数据(附加数据角色) (4).每一个数据项能够对数据状态进行控制(可编辑.可选...) 2.Qt中的通用模型类QStandardItemModel (1).QStandardItemModel继承自抽象的模型类QAbstractItemModel (2).QStand

第三课、初识程序的灵魂------------------------狄泰软件学院

一.初识程序的灵魂 1.数据结构静态描述了数据元素之间的关系 2.高效的程序需要在数据结构的基础上设计和选择算法 高效的程序需要: (1).恰当的数据结构 (2).合适的算法 3.算法是特定问题求解步骤的描述,在计算机中表现为指令的有限序列 (1).算法是独立存在的一种解决问题的方法和思想 (2).对于算法而言:语言不重要,重要的是思想 4.算法的特性 (1).输入:算法具有0个或者多个输入 (2).输出:算法至少有一个或者多个输出 (3).有穷性:算法在有限的步骤之后会自动结束而不会自动循环