Using RPointerArray<class T>

This document covers the issues involved in using a RPointerArray.

Freeing all memory before the array goes out of scope

By convention, class names starting with the letter R do not allocate memory on the heap. RPointerArray<class T> is an exception and this should be remembered when using the class.

If an array is declared on the program stack, then its Close() or Reset() member function must be called to ensure that allocated memory is freed.

Similarly, if RPointerArray<class T> is a data member of another class, then the destructor of that class must call Close() or Reset().

Another issue to remember is the ownership of objects whose pointers are contained within an RPointerArray<class T> array. If ownership of the objects lies elsewhere, then calling Close() or Reset() before the array goes out of scope is sufficient. If, however, ownership of these objects is vested in the array, and it is the intention that these objects be destroyed when the array is destroyed, then ResetAndDestroy() must be called before the array goes out of scope.

Packaging the algorithm for ordering array objects

A RPointerArray<class T> array allows its contained pointers to be ordered so that the objects themselves are in object order. The array provides the behaviour for inserting and sorting instances of pointers to the template class. To help with this, the template class must provide an algorithm for deciding how two template class objects are ordered. This algorithm is implemented by a function which must be wrapped in a TLinearOrder<class T> package.

The function implementing the algorithm can be a static member of the class but need not necessarily be so.

Here, we aim to build an array of CMyTest objects ordered in a way which makes sense for the CTMyTest class.

class CMyTest
 { 
public 
 ~CMyTest();
 Static CMytest* NewL(const TDesC& aText);
 static TInt Compare(const CMyTest& aFirst, const CMyTest& Second);
public:
 HBufC* iText;
 };

In this example, the algorithm is implemented by a static function called Compare(). It takes const references to two CMyTest objects and returns zero if the objects are equal, a negative value if aFirst is less than aSecond and a positive value if aFirst is greater than aSecond.

TInt CMyTest::Compare(const CMyTest& aFirst,const CMyTest& aSecond)
 {
 TInt ret = (aFirst.iText)->Compare(*aSecond.iText);
 if (ret > 0)
  return 1;
 if (ret < 0)
  return -1;
 return 0;
 }

Construct three CMyTest objects and then construct an array object for an array of pointers to CMyTest objects; the array has default granularity.

_LIT(KTextOne,"First Text");
_LIT(KTextTwo,"Second Text");
_LIT(KTextThree,"Third Text");
...
CMyTest* one   = CMyTest::NewL(KTextOne);
CMyTest* two   = CMyTest::NewL(KTextTwo);
CMyTest* three = CMyTest::NewL(KTextThree);
...
RPointerArray<CMyTest> x;

There are at least three ways of proceeding, some of which are more efficient than others.

  • Explicitly build a TLinearOrder<CMyTest> and pass this as a parameter to InsertInOrder().

...
TLinearOrder<CMyTest> order(CMyTest::Compare);
...
x.InsertInOrder(one,order);
...
  • Construct a temporary TLinearOrder<CMyTest> on the call to InsertInOrder().

...
x.InsertInOrder(one,TLinearOrder<CMyTest>(CMyTest::Compare));
...
  • Implicitly construct a temporary TLinearOrder<CMyTest> on the call to InsertOrder().

...
x.InsertInOrder(one,CMyTest::Compare);
...

This applies to all member functions of RPointerArray<class T> which take a TLinearOrder<class T> argument.