我们看如下的代码
代码:
class auto_ptr1
{
public:
resource_ptr pR;
auto_ptr1(resource_ptr pR):pR(p)
{
}
~auto_ptr1()
{
pR->Close();
}
};
class auto_ptr2
{
public:
resource1_ptr pR;
auto_ptr2(resource_ptr pR):pR(p)
{
}
~auto_ptr2()
{
pR->Close();
}
} ;
int main()
{
auto_ptr2 ptr2;
auto_ptr1 ptr1;
}
首先一大罪状是强买强卖强盗行径,如果ptr2和ptr1关闭是有先后顺序的,那么用auto_ptr就会出现关闭顺序的混乱。
如果某个程序要求ptr2先close,ptr1后close,那么上面的例子按照腿栈的顺序作dtor便出现
了关闭顺序的混乱。也就是说在这种情况下使用资源,要非常小心auto_ptr的定义顺序。然而定义顺序本来一个函数中
是没有任何关系的.更为要命的是,正常的关闭顺序必须和定义顺序相反。如果我们有这样两个
代码:
resource:
class Resource1
{
Resource1(arg);
close();
}
class Resource2
{
Resource2(arg);
close();
}
人家只提供ctor,不提供open这是非常正常的事情。如果打开的和关闭的顺序都要求是
resource1
resource2
那么auto_ptr无论如何不可能工作。要么打开顺序不正确,要么关闭顺序不正确。
第二条罪状是搭配出售奸商本质,如果我们假定上面的定义顺序是正确的dtor顺序,那么ptr1先dtor,ptr2后dtor
但是不要忘记close也是可以抛出exception的,那么如果ptr1的close出现异常ptr2是否会关闭呢?
经过我的试验,这是依赖编译器的。在BCB 6中ptr2的确能够正常被dtor,但是在vc7中则程序直接退出
大家可以尝试这段代码:
代码:
class auto_ptr1
{
public:
int * p;
auto_ptr1()
{
p=NULL;
}
~auto_ptr1()
{
throw 1;
}
};
class auto_ptr2
{
public:
int p;
auto_ptr2()
{
//p=NULL;
}
~auto_ptr2()
{
p=3;
printf("asdfasdf");
}
} ;
int main()
{
auto_ptr2 ptr2;
auto_ptr1 ptr1;
}
//bcb里面可以正确执行,而到了vc7中并没有直接打印出asdfasdf,
第三条罪状是假冒伪劣坑害百姓,elm为了解决这个问题,他可能提出这样的方案 auto_gc_ptr2<First,Second>
好啊,那么你要做多少个auto_gc_ptr,况且不是所有的resource都是使用close这个方式,有些用win32API来关闭的你怎么办,template根本帮不了的你的忙。你要做排列组合的traits,当然人家还会提出3个,4个我真的很同情你。
第四条罪状是虚假广告蒙骗群众,如果elm真的引入了auto_gc_ptr2,
且不论是否复杂它又要引入finally了
且看auto_gc_ptr2的代码
代码:
template<Frist,Second>
class auto_gc_ptr2
{
Frist __pF;
Second __pS;
auto_gc_ptr2(Frist pF,Second pS):__pF(pF),__pS(PS){}
~auto_gc_ptr2()
{
__pF.close();//抛出异常
__pS.close();//泄漏了finally赶快来救命啊。
}
}