现在的位置: 首页 > 综合 > 正文

Symbian新手入门:清除栈和两阶段构造函数

2012年12月29日 ⁄ 综合 ⁄ 共 1809字 ⁄ 字号 评论关闭

在创建实例的时候SymbianC++使用new(ELeave)来代替普通的new,比如:

  CBar*pBar=new(ELeave)CBar

  这个用法是考虑到手机特殊的属性:内存一般较小,经常会有内存不足的情况出现。

  在PC上如果内存不足我们就会退出程序,但是在手机不能那样频繁的退出,所以内存不足被划分为异常,需要离开。

  下面这个函数就会在内存不足的时候在A行离开:

void FooBarL()
{
CBar 
*pBar = new (ELeave) CBar; //A
User::LeaveIfError(pBar
->Foo()); //B
delete pBar; 
//C
}

  离开作为异常处理的机制,存在着一个问题。如果上面这个程序在B行Foo()返回了一个错误值,就会在那一行离开,但是系统为pBar指针分配的内存也就泄漏了。为了解决这个问题,Symbian程序中频繁使用CleanupStack(清洁栈),它的典型使用方式如下:

void FooBarL()
{
CBar 
*pBar = new (ELeave) CBar; //A

CleanupStack::PushL(pBar);
User::LeaveIfError(pBar->Foo()); //B
CleanupStack::Pop();

delete pBar; //C
}

  他的作用就是,在B行之前,把pBar指针放到清洁栈上,一旦B行离开了,清洁栈就会自动删除pBar回收内存,如果B行顺利通过,就可以通过pop把pBar拿下来了。

  CleanupStack有效地解决了这个潜在的内存泄漏问题,但是这个方法在一个特殊的情况下不适用。那就是如果一个类的构建函数离开,那么new为它分配的内存就会泄漏。(构建的顺序是:系统分配内存,然后运行构建函数)

  这个问题就导入了下一个概念:two-phaseconstruction(二层构建)

  我们的目标是:构建函数在任何情况下不可以离开!要实现它就必须:

  1。不在构建函数里使用任何L函数

  2。不在构建函数里分配内存

  凡是需要以上两个操作的都放到第二层构建函数中:ConstructL.要把两层构建结合起来,我们需要另一个静态函数,一般为NewL或者NewLC.L大家都知道代表离开,C代表清洁栈,下面会详细讲解NewLC的方便之处。

  二层构建的基本模式就是:

CHelloWorldBasicAppView* CHelloWorldBasicAppView::NewL(const TRect& aRect)
{
CHelloWorldBasicAppView
* self = CHelloWorldBasicAppView::NewLC(aRect);
CleanupStack::Pop(self);
return self;
}

CHelloWorldBasicAppView* CHelloWorldBasicAppView::NewLC(const TRect& aRect)
{
CHelloWorldBasicAppView
* self = new (ELeave) CHelloWorldBasicAppView;
CleanupStack::PushL(self);
self
->ConstructL(aRect);
return self;
}

void CHelloWorldBasicAppView::ConstructL(const TRect& aRect)
{
// Create a window for this application view
CreateWindowL();

// Set the windows size
SetRect(aRect);

// Activate the window, which makes it ready to be drawn
ActivateL();
}

  先看NewLC函数,它创建一个CHelloWorldBasicAppView的实例,然后把他放在清洁栈上,然后调用它的第二层构建函数(可以离开的),然后并没有把实例从清洁栈上取下就返回了。这样的好处就是如果我们用NewLC创建一个对象,然后调用它的可以离开的函数就不必把它放到清洁栈上,因为它已经在上面了。NewL的功能和NewLC是一样的,只是在返回实例前把它取下清洁栈。

  一般的C类都提供NewL,不是所有的C类都会提供NewLC.

抱歉!评论已关闭.