博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++ 智能指针(一)
阅读量:6256 次
发布时间:2019-06-22

本文共 2186 字,大约阅读时间需要 7 分钟。

  •   内存安全  

  在C++中,动态内存的管理是通过一对运算符来完成的:new,在动态内存中为对象分配空间并返回一个指向该对象的指针,我们可以选择对对象来进行初始化;delete,接收一个动态对象的指针,销毁该对象,并释放与之关联的内存。

  动态内存的使用很容易出问题,因为确保在正确的时间释放内存是及其困难的。有时我们会忘记释放内存(或程序抛出异常),在这种情况下就会产生内存泄漏;有时在尚有指针引用内存的情况下我们就释放了它,在这种情况下就会产生引用非法内存的指针(段错误)

  下面写个Demo测试程序  

#include 
#include
#define FLAG 3 //用于编译不同的程序class Demo1{public: Demo1() { std::cout << "Demo1" << std::endl; } ~Demo1() { std::cout << "~Demo1" << std::endl; }};bool throw_test(bool flag){ if (flag) { throw "throw_test"; } return flag;}int main(int argc, char* argv[]){ Demo1 *pDemo1 = new Demo1(); #if (FLAG == 1) throw_test(true);  //1.执行这条语句,会打印~Demo1? #endif #if (FLAG == 2) try { throw_test(true); } catch (...) //2....代表捕获所有异常 { delete pDemo1; //3.执行这条语句,会打印~Demo1? throw; } #endif #if (FLAG == 3) delete pDemo1; #endif return 0;}

  上述程序结果如下:

   当宏FLAG为1时,执行throw_test(true),即使程序抛出异常,它没有打印~Demo1;

  当宏FLAG为2时,执行throw_test(true),程序会抛出异常,之后捕获到异常打印~Demo1;

  当宏FLAG为3时,执行delete pDemo1,这是正常操作,程序会调用Demo1的析构函数,打印~Demo1;

 

  •  智能指针

  C++中的智能指针类型有:auto_ptr,shared_ptr,unique_ptr,weak_ptr(后三者为C++11新增的),它们均为类模板,使用需要包含<memory>头文件

  常规指针带来的风险

Demo1* pDemo1 = new Demo1();Demo1* pDemo2;pDemo2 = pDemo1;printf("pDemo1:%x pDemo2:%x\n", pDemo1, pDemo2); 

  上面的pDemo1和pDemo2是常规指针,指向同一个对象(浅拷贝),因此打印的地址也是一样的;请试想一下如果其中一个指针执行了delete操作,那么另一个指针再执行别的操作会怎样?程序会发生段错误。要避免这个问题,可以用下面这些方案:

  1. 定义赋值运算符函数,进行深拷贝,这样的操作会使上面的两个指针不再指向同一个对象,缺点是浪费空间,所以智能指针都未采用此方案
  2. "独占"所指的对象;对于特定的对象,某一时刻只能有一个指针指定一个给定对象,当指针被销毁时,它所指的对象也被销毁,这就是用于auto_ptr和uniqiie_ptr 的策略,但unique_ptr的策略更严格。
  3. 利用引用计数,创建记录型的指针;例如,赋值时,计数将加1,而指针过期时,计数将减1。当减为0时才调用delete。这是shared_ptr采用的策略。

 

  在C++11中,auto_ptr已弃用;编写一段测试程序,Demo1类还是使用上面定义的。

int main(int argc, char *argv[]){	std::auto_ptr
pDemo1(new Demo1); std::auto_ptr
pDemo2; pDemo2 = pDemo1; printf("pDemo1:%p pDemo2:%p\n", pDemo1, pDemo2);  //运行到这里pDemo1会打印什么? return 0;}

  上面的程序运行后,打印pDemo1的地址为NULL。具体可以查看下auto_ptr的赋值运算符的实现是如何的。

  下面这两张截图是VS2015下的auto_ptr的赋值运算符的实现;我们可以看到使用赋值运算符时,会调用reset函数,这是会将_Myptr的内存delete,并将地址置为NULL;如果pDemo1调用成员函数,此时会发送什么?

 

 

 

 

                   

 

 

    

  

  auto_ptr存在内存崩溃的风险,这个或许就是auto_ptr被C++11弃用的原因吧。

  未完待续...

转载于:https://www.cnblogs.com/coder-zyc/p/9521260.html

你可能感兴趣的文章
Java内存分配和内存管理
查看>>
CNCF 有哪些具体的项目内容?
查看>>
[转]Oracle 清除incident和trace -- ADRCI用法
查看>>
农产品期货普遍回调 短期压力仍较大
查看>>
数据之路 Day8 Matplotlib包
查看>>
Ye.云狐J2刷机笔记 | 完美切换内部存储卡和SD卡的改法.vold.fstab
查看>>
【转】WIFI基本知识整理
查看>>
普通GRE 隧道配置
查看>>
Vim编程常用命令
查看>>
【树莓派】RASPBIAN镜像初始化配置
查看>>
在按钮上添加倒计时激活功能(转自手册网)
查看>>
java过滤敏感词汇
查看>>
类似LIS+贪心(ZOJ1025)
查看>>
[C++再学习系列] 虚函数的4条规则
查看>>
Thread.sleep
查看>>
浅析 ThreadLocal
查看>>
Pycharm批量操作代码快捷键
查看>>
oracle备份与恢复
查看>>
LLDB调试器
查看>>
cordova Ionic 和cordova的区别是什么
查看>>