原文出處: 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<>。
注意事項:
- RArray和RPointerArray都是基於模板的
- RArray的模板參數應該爲R類或T類,而RPointerArray的模板參數可以是任意類型
- RArray是固定長度對象的集合(最小長度爲4個字節,對象的sizeof必須>4!),RPointerArray是對象指針的集合
- 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();
}
二、使用集合時的內存管理問題
- 如果使用RArray類,模板對象所佔字節必須>=4個字節,以下代碼將引發嚴重異常:
class TTestClass
{
public:
TUint8 iX;
TUint8 iY;
};
RArray<TTestClass> iArray;
LOCAL_C void MainL()
{
TTestClass testClass1;
iArray.Append(testClass1);
} - 因爲是RArray和RPointerArray爲R類,R類都要求調用Close方法以關閉句柄釋放資源,所以必須使用CleanupClosePushL方法將集合入棧,這樣才能在異常退出時,程序自動調用Close方法
- 如果將一個對象加入了集合類,則應該遵循“集合擁有對象”的準則,對象的生命週期由集合管理,集合銷燬時會將對象銷燬
- 調用AppendL方法前,將要加入的對象加入清理棧中以防AppendL異常退出:
CTest* test = CTest::NewL();
CleanupStack::PushL(test);
array.AppendL(test);
CleanupStack::Pop(test); - RArray和RPointerArray都實現了Reset方法,用於釋放所有分配用於存儲元素的內存。RPointerArray實現了ResetAndDestroy方法,用於釋放指針所指向的對象和指針本身。介於第2點“集合擁有對象”,我們應該使用RPointerArray::ResetAndDestroy方法