1. 永恒的话题:内存泄漏

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

(2)C++语言中没有垃圾回收的机制

(3)指针无法控制所指堆空间的生命周期------------指针是变量,可以指向内存堆空间,但是无法控制所指堆空间的生命周期

说明内存泄漏:

 #include<iostream>
#include<string> using namespace std; class Test
{
int i; public: Test(int i)
{
this->i = i;
} int value()
{
return i;
} ~Test()
{
}
}; int main()
{
for (int i = ; i < ; i++)
{
Test* p = new Test(i); //P指向堆空间的对象
//指针是局部变量for()循环之后消失,但是指针开辟的空间没有进行释放 内存泄漏
//长时间运行会出现Bug cout << p->value() << endl; } return ;
}

2. 深度的思考:我们需要什么?

(1)需要一个特殊的指针指针生命期结束时主动释放堆空间

(2)一片堆空间最多只能由一个指针来标识------------避免内存多次释放

(3)杜绝指针运算指针比较-----------因为只有一个该类对象的指针能指向堆空间,避免指针越界,野指针

3. 解决方案

定义一个对象,让对象取模拟真正意思上的指针行为---------对象代替指针,称该对象为智能指针 -------智能指针本质:是个对象

(1)重载指针特征操作符( -> 和 * )

(2)只能通过类的成员函数重载

(3)重载函数不能使用参数

(4)只能定义一个重载函数

(5)注意:智能指针只能用来指向堆空间中的对象或变量(不能指向栈)

实验:(1)实现特殊的指针指针生命期结束时主动释放堆空间

 #include<iostream>
#include<string> using namespace std; class Test
{
int i;
public:
Test(int i)
{
cout <<"Test (int i)"<< endl; this->i = i;
}
int value()
{
return i;
}
~Test()
{
cout << "~Test ()" << endl;
} }; //智能指针 本质是对象--------首先创建智能指针类
class Pointer
{
Test* mp; //指针mp指向对象Test,用于保存要被管理对象的指针 public: //构造函数被堆空间上内存地址初始化 Pointer(Test* p = NULL) //指针被堆空间上的地址初始化---参数Test*指针
{
mp = p;
} //重载->操作符 Test* operator -> () //不能使用参数,所以也就只能定义一个重载函数
{
return mp; //返回成员指针
} //重载*操作符 Test& operator * () //不能使用参数,所以也就只能定义一个重载函数
{
return *mp; //*作用指针意义:返回当前指针所指变量或对象
} ~Pointer()
{
delete mp; //智能指针被析构时,同时删除其所管理的Test类的对象,释放成员指针指向的堆空间
}
}; int main()
{
for (int i = ; i < ; i++)
{
// Test* p = new Test(i); //那么就可以用类对象名代替指针 Pointer p = new Test(i); //可以动态的将申请的空间释放 cout << p->value() << endl; // }
return ;
}

实现:一片堆空间最多只能由一个指针来标识------------避免内存多次释放

    不进行指针运算和比较

    方法:重载赋值操作符和拷贝构造

 #include<iostream>
#include<string> //智能指针 本质是对象
using namespace std; class Test
{
int i;
public:
Test(int i)
{
cout <<"Test (int i)"<< endl;
this->i = i;
}
int value()
{
return i;
}
~Test()
{
cout << "~Test (int i)" << endl;
} }; class Pointer
{
Test* mp; //数据成员为指针 public: Pointer(Test* p = NULL) //构造函数被堆空间上内存地址初始化
{
mp = p;
} // 实现一片堆空间最多只能由一个指针标识 杜绝多次释放 //拷贝构造函数
Pointer(const Pointer& obj) //自定义深拷贝构造函数
{
// delete mp; //拷贝构造阶段,mP野指针不能删除---内存错误 mp = obj.mp; //当前对象的成员指针mp指向初始化对象的成员指针所对应的堆空间---两个指针指向一片内存空间
//初始化对象把他指向的堆空间完全交给当前对象-----------即保证只有一个智能指针指向同一片内存 const_cast<Pointer&>(obj).mp = NULL; //所有权的传递,自己置空 const_cast去除只读属性
} //赋值操作符重载函数
Pointer& operator=(const Pointer& obj) // 1,返回值类型一定是引用Test&为了连续赋值 2,参数是const引用类型
{
//进行赋值操作
if (this != &obj) //3,赋值操作符不是自赋值a=a,要避免赋值,通过This判断,this指向当前对象的地址和参数地址不同才进行赋值操作
{
delete mp; mp = obj.mp; //保证赋值操作时,只能由一个智能指针指向同一堆空间 const_cast<Pointer&>(obj).mp = NULL;
}
return *this; //4,返回当前对象地址
} //重载指针特征操作符
Test* operator -> ()
{
return mp; //返回成员指针
}
Test& operator * ()
{
return *mp; //返回当前指针所指变量或对象
} bool isNull() //判断当前智能指针是否为空
{
return(mp == NULL);
} ~Pointer()
{
delete mp;
}
}; int main()
{
Pointer p1 = new Test(); //定义智能指针P1 cout << p1->value() << endl; // Pointer p2 = p1; //定义智能指针P2,用p1进行初始化,p1管理的堆空间转给P2 //不能指针比较的指针运算
// p2++;
// if(p1==p2) cout << p1.isNull() << endl; //1空 p1指向NULL,不再指向原来的堆空间 cout << p2->value() << endl; //0 p2接管P1指向的堆空间------管理92行堆对象

    //p2++;不重载++,因为每次只能一个智能指针指向堆空间,这种++操作没意义
  

       //p2智能指针生命期结束,会自动释放接管的堆空间
 return ;  }

//输出结果:

//Test(int i)

//5

//1

//5

//~Test()

存在问题: 智能指针对应的类只能指向Test固定的类类型,不能指向其他类型,能不能指向各类他能管理的类类型------以后会学到模板实现

4. 小结

      掌握智能指针的创建

   智能指针在自己生命周期结束,自动释放所指的内存空间

   要求c++避免使用原生指针,那么以后就可以使用智能指针

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

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

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

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

最新文章

  1. tyvj1198 最优矩阵连乘
  2. NIO 连接
  3. Leetcode 111 Minimum Depth of Binary Tree 二叉树
  4. Struts2 中遇到的问题
  5. Linux scp 远程文件/目录传输
  6. [ActionScript 3.0] Away3D 旋转效果
  7. 1081. Rational Sum (20)
  8. MSP430F149模拟IIC读写24C02程序
  9. windows下配置PHP+Nginx+MySQL完整流程(转)
  10. Windows下python安装MySQLdb
  11. jxls2.3-简明教程
  12. 通过EXPLAIN分析低效SQL的执行计划
  13. 1.2为什么需要public static void main(String[] args)这个方法
  14. 2017年Kali Linux更新源
  15. IDEA 编译 Jmeter 4.0 ( 二次开发_1 )
  16. 机器学习---朴素贝叶斯分类器(Machine Learning Naive Bayes Classifier)
  17. LostRoutes项目日志——敌人精灵Enemy解析
  18. 白鹭引擎 - 绘制圆形的进度条 ( graphics )
  19. HTML5 FileReader
  20. PHPCMS之 列表和内容页

热门文章

  1. Web安全之验证码绕过
  2. Java 反射简介
  3. caffe的python接口学习(3)训练模型training
  4. 【Python3爬虫】模拟实现小牛在线登录过程
  5. 程序员的修炼-我们为什么会编写BUG
  6. 错误记录——fail: Microsoft.AspNetCore.Server.Kestrel[13]
  7. [Python] datetime.timedelta模块用法
  8. 移动端Retina屏boder 1px显示为2px或3px的解决方法
  9. Xshell6 优化
  10. jvm之栈、堆