Symbian基礎總結 -- RArray和RPointerArray

 原文出處: http://www.cnblogs.com/felixYeou/archive/2008/11/18/1336055.html

 

Symbian OS不支持STL,主要原因是因爲STL覆蓋的面太廣,不適合在內存受限的設備上使用。

在這裏我們首先學習RArray模板類。如果您有java或者.net方面的經驗,Symbian中的RArray和RPointerArray類似於java中的Vector<>或.net中的List<>。

注意事項:

  1. RArray和RPointerArray都是基於模板的
  2. RArray的模板參數應該爲R類或T類,而RPointerArray的模板參數可以是任意類型
  3. RArray是固定長度對象的集合(最小長度爲4個字節,對象的sizeof必須>4!),RPointerArray是對象指針的集合
  4. RArray和RPointerArray應該創建在棧上,或者爲C類的成員變量

接下來我們將針對RArray和RPointerArray的幾個常用的方法進行介紹,以下所有演示代碼都在控制檯程序中執行。

 

一、常用方法

1、[]操作符

RArray重載了[]操作符:

 

inline const T &operator[](TInt anIndex) const;
inline T &operator[](TInt anIndex);

 

 

2、添加元素,Append和AppendL方法: 
首先我們使用一斷代碼來說明Append(L)的使用方法:

_LIT(KText1, "Hello world  1");
_LIT(KText2, "Hello world 2");

RArray<TDesC> array;
array.Append(KText1());
array.Append(KText2());

console->Write(array[0]);

array.Reset();
array.Close();

按照我們的理解,控制檯輸出的應該是“Hello World 1”,但事實上,控制檯輸出的是亂碼,爲什麼呢?

我們上面的注意事項中的第三點:“RArray是固定長度對象的集合”,模板參數的長度在RArray構建時被確定,但是TDesC類型的長度明顯是可變的(TDesC爲描述符的基類,描述符的派生類的長度會根據包含的內容改變),所以在此得不到正確的結果。

因爲,我們在創建RArray的時候確定描述符的大小就可以了,有兩種方法:

_LIT(KText1, "Hello world  1");
_LIT(KText2, "Hello world 2");

RArray<TPtrC> array;
array.Append(KText1());
array.Append(KText2());

console->Write(array[0]);

array.Reset();
array.Close();

typedef TBufC<20> TBufParam; 

_LIT(KText1, "Hello world 1");
_LIT(KText2, "Hello world 2");

RArray<TBufParam> array;
array.Append(KText1());
array.Append(KText2());

console->Write(array[0]);

array.Reset();
array.Close();

3、排序,Sort方法

在.net中,實現排序方法必須要實現一個委託,此委託將傳入的兩個變量進行比較,然後返回比較後的值給排序方法。

在Symbian OS中的機制類似,它使用TLinearOrder對象使用函數指針綁定一個比較函數,注意:此函數必須是靜態函數、全局函數或命名空間的函數,在RArray的Sort方法內傳入這個TLinearOrder對象。

TInt CompareTPtrC(const TPtrC& aLeft, const TPtrC& aRight) 
{
return aLeft.Compare(aRight);
}

LOCAL_C void MainL()
{
_LIT(KText1, "Hello world 2");
_LIT(KText2, "Hello world 1");


RArray<TPtrC> array;
array.Append(KText1());
array.Append(KText2());


TLinearOrder<TPtrC> order(CompareTPtrC);
array.Sort(order);


console->Write(array[0]);


array.Reset();
array.Close();
}

經過排序後,返回的結果爲“Hello world 1”

 

4、查找

查找與排序類似,都要實現一個委託來判斷兩個變量是否相同,此次使用TIdentityRelation類對比較函數進行封裝。同樣的,此比較函數必須是靜態函數、全局函數或命名空間的函數。

RArray::Find方法的第一個參數爲要查找的對象,第二個參數爲封裝了比較函數的TIdentityRelation對象。

TBool CompareTPtrC(const TPtrC& aLeft, const TPtrC& aRight)
{
return aLeft.Compare(aRight) == 0 ? ETrue : EFalse;
}

LOCAL_C void MainL()
{
_LIT(KText1, "Hello world 2");
_LIT(KText2, "Hello world 1");

RArray<TPtrC> array;
array.Append(KText1());
array.Append(KText2());

TIdentityRelation<TPtrC> relation(CompareTPtrC);
TPtrC ptr(_L("Hello world 1"));
TInt index = array.Find(ptr, relation);

console->Write(array[index]);

array.Reset();
array.Close();
}

 

二、使用集合時的內存管理問題

  1. 如果使用RArray類,模板對象所佔字節必須>=4個字節,以下代碼將引發嚴重異常: 
    class TTestClass
    {
    public:
    TUint8 iX;
    TUint8 iY;
    };

    RArray<TTestClass> iArray;

    LOCAL_C void MainL()
    {
    TTestClass testClass1;
    iArray.Append(testClass1);
    }
  2. 因爲是RArray和RPointerArray爲R類,R類都要求調用Close方法以關閉句柄釋放資源,所以必須使用CleanupClosePushL方法將集合入棧,這樣才能在異常退出時,程序自動調用Close方法
  3. 如果將一個對象加入了集合類,則應該遵循“集合擁有對象”的準則,對象的生命週期由集合管理,集合銷燬時會將對象銷燬
  4. 調用AppendL方法前,將要加入的對象加入清理棧中以防AppendL異常退出: 

    CTest* test = CTest::NewL();
    CleanupStack::PushL(test);

    array.AppendL(test);

    CleanupStack::Pop(test);
  5. RArray和RPointerArray都實現了Reset方法,用於釋放所有分配用於存儲元素的內存。RPointerArray實現了ResetAndDestroy方法,用於釋放指針所指向的對象和指針本身。介於第2點“集合擁有對象”,我們應該使用RPointerArray::ResetAndDestroy方法
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章