At this time, I will try to show you how (and why) to create the methods NewL and NewLC. Commonly, Symbian OS classes offers these two static method implementations. A lot of classes defines and implements these two methods, and there is a reason for that...
The process used to create and define is called "two-phased construction". This process is described as a effort to prevent that a object creation throw an exception. The object construction process is divided in two-phases: On the first phase, the object is instantiated (using new (ELeave), for example) and a memory chunk is reserved for that object;
The second phase is where the object data and member variables are initiated (ConstructL phase).
The two-phased construction is an interesting solution, because we can separately threat 2 critical phases in the object initialization. Between these two phases, we will use the CleanupStack::PushL, to guarantee that this temporary class instance would eventually be disposed and cleaned from memory. The next stage, the ConstructL method is called. The piece of code below will try to show you how to make it:
{
CUser* self = new (ELeave) CUser( aObserver );
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
The NewLC method is very simple: it only calls a new operator that can LEAVE (ELeave constant), pushs this temporary class instance to the Cleanup Stack, and follows with a call to ConstructL defined in this temporary instance. After that, is preconceived that the object is well initialized.
Below you will find a NewL implementation code example:
{
CUser* self = new (ELeave) CUser( aObserver );
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(self);
return self;
}
Perceive a Pop() method call after ConstructL() is called. This guarantees that this variable reference was "well-initialized", and the CleanupStack already can clean its reference from heap memory space.
The code below is a optimized NewL, which uses the NewLC implementation in it. Tha main advantage from this new code is that the code is smaller than last one...
{
CUser* self = NewLC( aObserver );
CleanupStack::Pop(self);
return self;
}
And a ConstructL example implementation:
{
iObserver = CUserStateObserver::NewL( this );
iName = TBufC::NewL( 100 );
iAge = 0;
LoadPluginsL();
}
The NewL and NewLC methods are declared as the following code (located in CUser.h):
{
public:
static CUser* NewL( MUserStateObserver* aObserver );
static CUser* NewLC( MUserStateObserver* aObserver );
.
.
.
But, the MAIN question: when should we choose between a NewL and a NewLC? What's the main difference?
I should say you that you can ALWAYS call NewL for member variables (class or instance variables), and NewLC for automatic variables (variables declared inside a method's body). It's happen because the member variables aren't immediately cleaned from CleanupStack, unless the object maintaining these members was disposed from CleanupStack space. The member variables have a longer life time, and is desired that its CleanupStack reference may be cleaned as soon as possible. The opposite occurs with the automatic variables: they will always be cleaned by CleanupStack when the method reachs the last instruction from method's body. So, if this method, containg NewLC references, can "Leave", the external trap harness will clean this automatic variables references, and pops it.
So, everytime in our code we call NewL inside a function that can LEAVE, we are wasting performance, because this object reference will be cleaned two times, one time by NewL (CleanupStack::Pop()), and another time by the TRAP harness that is related to this function call.