Symbian编程-集合与缓冲区(1)-RArray和RPointerArray

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方法

  转自:   http://www.cnblogs.com/felixYeou/archive/2008/11/20/1337780.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值