exception类所以定义的唯一操作是一个what的虚成员,返回const char 的对象,一般返回用来在抛出位置构造异常对象的信息
|---overflow_error
|--runtime_error---|---underflow_error
| |---range_error
|
|---bad_cast
exception----|
|---bad_alloc
| |---domain_error
| |---invalid-argument
|---logic_error--|---out_of_range
|---length-error
//throw exception if both objects do not refer to the same
Sales_item operator+(const Sales_item &lhs,const Sales_item &rhs)
{
if( !rhs.same_isbn(rhs) )
{
throw isbn_mismatch("ISBN mismatch",lhs.book(),rhs.book());
}
Sales_item ret(lhs);
//copy lhs into a local object,that we'll return
ret += rhs;
return ret; //return ret by value
}
//use hypothctical bookstore exception
Sales_item item1,item2,sun;
while( cin >> item1 >> item2 ) //read two transactions
{
try
{
sum = item1 + item2; //calculate their sum
}
catch( const isbn_mismatch &e )
{
cerr << e.what() << ":left isbn(" << e.left << ")right isbn(" << e.right << ")" << endl;
}
}
自动资源释放的问题,来考虑如下函数
void f()
{
vector<string> v; //local vector
string s;
while( cin >> s )
{
v.push_back(s); //populate the vector
}
string *p=new string[v.size()]; //dynameic array
delete []p;
}//v destroyed antomatically when the function
这个函数定义了一个局部vector并动态分配了一个数组,在正常情况下,数组合vector都在退出函数前被撤销,函数中最后一个语句释放数组,在函数结束时自动撤销vector
但是,如果在函数内部发生异常,则撤销vector而不释放数组,在new之后但在delete之前发生的异常时的数组没被撤销。这时,可通过定义一个泪来封装资源的分配和释放,这一技术称为“分配既初始化” ,简称RAII。
class Resource
{
public:
Resource(parms p):r(allocate(p)){}
~Resource(){release(r);}
//also heed to define copy and assigment
private:
resource_type *r;//resouce managed by this type
resource_type *allocate(parms p);//allocate
void release(resource_type *);//free this resource
};
Resource类分配资源和回收资源的类型,它保存表示资源的数据成员
void fcn()
{
Recouse res(args);//allocates resourse_type
//code that might throw an exception
//if exception occurs,destructor for res is run
//automatically
//...
}
资源分配技术中的auto_ptr类:
auto_ptr类在头文件memory中
auto_ptr<T> ap; 创建为ap的为绑定的auto_ptr对象
auto_ptr<T> ap1(p); 创建名为ap1的auto_ptr对象,ap1拥有指针p指向的对象,构造函数为explicit
auto_ptr<T> ap1(ap2); 创建名为ap1的auto_ptr对象,ap1保存原来存储在ap2中的指针,将所有权转移给ap1,ap2成为未绑定的 auto_ptr对象
ap1=ap2; 向所有权从ap2转给ap1,删除ap1的对象并且使ap1指向ap2指向的对象,使ap2未绑定
ap.reset(p); 如果p与ap值不同,则删除ap指向的对象,并且将ap邦到p
ap.release(); 返回ap所保存的指针并且使ap成为未绑定
ap.get(); 返回ap保存的指针
auto_ptr不能用于管理从new返回的一个对象,不能管理动态分配数组,当auto_ptr被复制或赋值德时候,会出错,且不能将其存储在标准库容其中
void f()
{
int *p=new int(42); //dynamically allocate a new obj
delete p;
}
如果在上述代码的new和delete之间发生异常,且不被局部捕获,则永远不会受内存,则用auto_ptr可以改善
void f()
{
auto_ptr<int> ap(new int(42)); //allocate new obj
//...
} //auto_ptr freed automatically when funcation ends
auto_ptr类可以接受任何类型指针的模板
auto_ptr<string> ap(new string("Banana"));
任意auto_ptr对象初始化是由new表达式返回的对象的地址接受构造函数explicit。所以必须使用初始化的直接形式来创建auto_ptr对象
autp_ptr<int> pi=new int(1024); //error
auto_ptr<int> pi=(new int(1024)); //ok
auto_ptr<string> ap1(new string("stegos"));
auto_ptr<string> ap2(ap1);
当复制auto_ptr对象或者对auto_ptr对象赋值时,右边的auto_ptr对象让出对基础对象的所有职责,并重置为未绑定的auto_ptr,若不置为空对象,则当删除所有指向内存时,就会重复删除
如要测试auto_ptr对象是否有效,可以通过get成员函数,返回包含auto_ptr对象中的基础指针
//revised test to guarantee p_auto reders to an obj
if( auto_ptr.get() )
{
//...
}
auto_ptr对象与内置指针的另外一个区别是,不能直接将一个地址赋给auto_ptr对象,相反,必须调用reset函数
if( !auto_ptr.get() )
{
auto_ptr.reset(new int(1024));
}