#ifndef __TOOLS_H__#define __TOOLS_H__#include <iostream>#include <string>class Trace{public:Trace(const std::string & pFunc):mFunc(pFunc){std::cout<<"Enter"<<" "<<mFunc<<std::endl;}~Trace(){std::cout<<"Exit"<<" "<<mFunc<<std::endl;}private:std::string mFunc;};#define trace Trace lUsetoTrace(std::string(__FUNCTION__));#endif
#include <memory>#include <stdexcept>#include <vector>#include "Tools.h"using namespace std;//基本原理:在return函數或有異常發生函數結束時,靜態變數的解構函式會自動執行class TestClass{public://如何管理類成員動態記憶體TestClass(){/*使用異常保證由類管理的動態記憶體不會泄露使用try因為我們在類中使用了指標維護動態記憶體而 tag 0 地區可能會有異常這導致了mDymnic指向的動態記憶體泄露使用異常保證了發生異常a被正確回收但這僅對建構函式的情況有效,因為沒有return*/try{tracemDymanic = new int;//tag 0 start//...throw runtime_error("TestSub Init Failed!");//tag 0 end}catch(exception &e){cout<<"E:"<<endl;cout<<" "<<e.what()<<endl;cout<<" "<<"delete a.."<<endl;delete mDymanic;throw runtime_error("TestClass init error!");}}//如何管理臨時動態記憶體void print(){cout<<"start ";cout<<*mDymanic;cout<<" end"<<endl;/*不使用new來開闢多餘一個的臨時空間或成員空間而使用標準庫代替使用智能指標維護單個臨時對象的使用try因為tag 1 中可能有異常或return發生將導致使用new分配的記憶體無法正確的和delete配對使用靜態變數管理動態記憶體將保證解構函式的執行,從而delete記憶體*/try{//auto_ptr 沒有非配數組的版本,使用標準庫來管理buffer是準確的vector<char> lbuffer(100);char *buffer = lbuffer.data();size_t bufferLen = lbuffer.size();//start to use buffer auto_ptr<int> p(new int);//tag 1 start//...//int *p = new int;throw runtime_error("dynamic error!");return ;//這個delete可能永遠都不會執行因為前面的程式流可能會先return或有異常從而結束函數//所以靠下面的delete總會執行來保證new分配的記憶體會被回收是顯然不行的//delete p;//tag 1 end}catch(exception &e){cout<<"E:"<<endl;cout<<" "<<e.what()<<endl;throw runtime_error("print failed!");}}~TestClass(){cout<<"TestClass uninit"<<endl;delete mDymanic;}private:int *mDymanic;};int main(){try{traceTestClass t;t.print();}catch(exception &e){cout<<"E:"<<endl;cout<<" "<<e.what()<<endl;cout<<" "<<"Main catch a except.."<<endl;}return 0;}