tr
的定义里,auto_ptr默认是auto_ptr
。auto_ptr
与auto_ptr
是两个不同的类,它们是相互独立的。
因此就不难理解为什么要这样定义:
auto_ptr (auto_ptr& a) throw(); // the para's type is auto_ptr
template
auto_ptr (auto_ptr
& a) throw(); // the para's type is auto_ptr
instead of auto_ptr
相似的,重载”=”的两个函数也不难理解了。
但是其实,不加auto_ptr (auto_ptr& a) throw();
好像也没有什么问题,因为编译器一般都会优先调用用户定义的函数。但是为了保险起见,还是加上为好。因为传入相同类型,编译器有调用默认构造函数的可能。
接着是重载 * 与 ->, 应该不难理解。
//Dereference----------------------------------------------------(3)
T& operator*()const throw()
{
return *ap;
}
T* operator->()const throw()
{
return ap;
}
再接着就是获取成员指针的函数。
//value access
T* get()const throw() // interface for getting ap
{
return ap;
}
//release owner ship
因为ap是私有成员,需要get()函数提供一个访问的接口。
然后继续, 进行成员指针重置的函数。
//reset value
void reset(T* ptr = 0)throw()
{
if(ap != ptr)
{
delete ap; // very important , it avoid the storage leak
ap = ptr; // assign of ap
}
}
最后是在定义auto_ptr的一个代理类。刚开始我很疑惑,为什么要再定义一个代理类,有什么不能通过auto_ptr解决么?原来auto_ptr的复制构造函数是有缺陷的。当传入的参数为左值时,可以正常编译,但是一旦传入的参数为右值时,g++上就编译不通过了。(左值右值在后面我会讲解)因为右值引用必须为const引用。
//Special conversions-----------------------------------------------(5)
template
struct auto_ptr_ref // define a reference to automatic pointer { Y *yp; auto_ptr_ref(Y *rhs):yp(rhs){} // constructor }; auto_ptr(auto_ptr_ref
rhs)throw():ap(rhs.yp) {} // put auto_ptr_ref's object as a para auto_ptr& operator=(auto_ptr_ref
rhs)throw() { reset(rhs.yp); return *this; } /*here is the data_transformation. With the help of it, it solves the bug of auto_ptr */ template
// transform data_type to auto_ptr_ref operator auto_ptr_ref
()throw() { return auto_ptr_ref
(release()); } template
// transform data_type to auto_ptr operator auto_ptr
()throw() { return auto_ptr
(release()); }
5. 左值与右值
在查阅资料之前,我也是误解了左值与右值的定义。左值与右值常见的误区在与:认为等号左边就是左值,等号右边就是右值。其实不然,等号只是左值右值中的一个特例,并不能用于概括左值与右值的概念,即并不适用于所有地方。其实,左值与右值是相对于表达式而言,当一个表达式执行结束以后,若该对象仍恒定存在,那么说明该对象是一个左值。如果在表达式结束后,该对象不存在,说明该对象是一个临时对象,即为右值。