标签:原因 image 实现 函数 情况 strong except return dem
在C++中,动态内存的管理是通过一对运算符来完成的:new,在动态内存中为对象分配空间并返回一个指向该对象的指针,我们可以选择对对象来进行初始化;delete,接收一个动态对象的指针,销毁该对象,并释放与之关联的内存。
动态内存的使用很容易出问题,因为确保在正确的时间释放内存是及其困难的。有时我们会忘记释放内存(或程序抛出异常),在这种情况下就会产生内存泄漏;有时在尚有指针引用内存的情况下我们就释放了它,在这种情况下就会产生引用非法内存的指针(段错误)。
下面写个Demo测试程序
#include <memory> #include <exception> #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操作,那么另一个指针再执行别的操作会怎样?程序会发生段错误。要避免这个问题,可以用下面这些方案:
在C++11中,auto_ptr已弃用;编写一段测试程序,Demo1类还是使用上面定义的。
int main(int argc, char *argv[]) { std::auto_ptr<Demo1> pDemo1(new Demo1); std::auto_ptr<Demo1> 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弃用的原因吧。
未完待续...
标签:原因 image 实现 函数 情况 strong except return dem
原文地址:https://www.cnblogs.com/coder-zyc/p/9521260.html