假设已经存在一个类的定义,类名为:httpcon。构造函数的定义为httpcon()。
现在我们将要用j2me(java me或者kjava)和symbian(cpp的一种)方式声明一个该类的实例。
java:
try
{
httpcon ht=httpcon();
}
catch(...)
{...}
这样在j2me中,已经算是该类的实例已经成功了,且进行了内存分配,也包含了相应的错误处理。
再来看下symbian:
httpcon* ht=new httpcon;
1)可以执行,但是这样的代码是会出错的,因为没有考虑分配失败的情况。
所以,请加上(Eleave) ,改成:
httpcon* ht=new (Eleave)httpcon;
将由Eleave自动来处理内存分配失败导致的后续代码错误。
2)httpcon* ht=new (Eleave)httpcon;这样的代码算是可以了吧?
symbian告诉我们,这样的代码,看起来很安全,但仍然不能保证绝对的内存安全,反例如以下代码:
class CY:public Cbase
{
public:
CY();
~CY();
public:
CX* iX;
};
CY::CY()
{
iX=new (Eleave)CX;
}
CY::~CY()
{
delete iX;
}
以上代码:
如果在执行CY的内存分配时,如果出错,那么在CY自身的构造函数即返回(没到CX构造函数),由Eleave处理并返回,所以没错。
如果在执行CY构造函数正确,在分配内部类CX时出错,CX可以由(Eleave)正确处理并返回,但遗漏了之前分配的CY,CY成为孤立对象,即内存泄漏。
所以以上代码是不正确的。
3)symbian要处理这个问题,新增了一条规则:“在构造函数中不能包含任何可能退出的函数”。
所以,CX的构造函数不能放在CY的构造函数中,而应该在CY分配成功后,将CY存入“清除栈”,将原先的构造函数,分为两部分,一部分CY的构造函数(不含任何可能导致退出的函数),另一部分“第二阶段构造函数”(可能导致退出的函数)。
在进行了第一部分构造函数后,将CY存入“清除栈”,再进行“第二阶段构造函数”,如果错误退出,那么系统在推出时将清除“清除栈”中的所有内容。这样就解决了前面的问题。
一行类构造体的代码,区别如此之大,考虑如此之全,效率要求如此之高....
你说有这样的程序员,他不拿高薪,谁拿?