一、各种类型缀名称说明:
保存类型:
Fix: 元素的实例占用的内存大小是相同,并且会将对象拷贝到向量中;
Var: 元素大小可以不相同,并且只是将元素的指针放到向量中;
Pak: 元素大小可以不同同,并且拷贝了元素的内容,是以长度+内容来保存的;
Ptr: 保存从CBase派生元素指针;
内存配置:
Flat: 连续内存; 类似: Array
Seg: 不连续内存;类似: List
如下图所示:
二、 具体类的功能查看帮助,派生图如下:
三、CArrayX 使用例子:
class TTask // Basic T class, represents a task
{
public:
TTask(const TDesC& aTaskName);
void ExecuteTaskL() {}; // Omitted for clarity
private:
TBuf<10> iTaskName;
};
TTask::TTask(const TDesC& aTaskName)
{ iTaskName.Copy(aTaskName); }
// Holds a dynamic array of TTask pointers
class CTaskManager : public CBase
{
public:
static CTaskManager* NewLC();
~CTaskManager();
public:
void AddTaskL(TTask* aTask);
void InsertTaskL(TTask* aTask, TInt aIndex);
void RunAllTasksL();
void DeleteTask(TInt aIndex);
public:
inline TInt Count()
{return (iTaskArray->Count());};
inline TTask* GetTask(TInt aIndex)
{return(iTaskArray->At(aIndex));};
private:
void ConstructL();
CTaskManager() {};
private:
CArrayPtrSeg<TTask>* iTaskArray;
};
const TInt KTaskArrayGranularity = 5;
CTaskManager* CTaskManager::NewLC()
{
CTaskManager* me = new (ELeave) CTaskManager();
CleanupStack::PushL(me);
me->ConstructL();
return (me);
}
CTaskManager::()
{// Cleanup the array
if (iTaskArray)
iTaskArray->ResetAndDestroy(); // Destroys objects through ptrs
delete iTaskArray;
}
void CTaskManager::ConstructL()
{
iTaskArray =
new (ELeave) CArrayPtrSeg<TTask>(KTaskArrayGranularity);
}
void CTaskManager::AddTaskL(TTask* aTask)
{ // Add a task to the end of array
// No need to check that aTask! =NULL because CBufBase does this
// before appending it
iTaskArray->AppendL(aTask);
}
void CTaskManager::InsertTaskL(TTask* aTask, TInt aIndex)
{ // Insert a task into a given element index
// No assertion on aTask or aIndex because CArrayFixBase
// and CBufBase do this
iTaskArray->InsertL(aIndex, aTask);
}
void CTaskManager::RunAllTasksL()
{ // Iterates all TTask objects and calls ExecuteTaskL()
TInt taskCount = iTaskArray->Count();
for (TInt index = 0; index < taskCount; index++)
{
(*iTaskArray)[index]->ExecuteTaskL();
}
}
void CTaskManager::DeleteTask(TInt aIndex)
{ // Removes the pointer from the array
// The function stores a pointer to it so it can be destroyed
TTask* task = iTaskArray->At(aIndex);
if (task)
{
iTaskArray->Delete(aIndex); // Does not delete the object
delete task; // Deletes the object
}
}
// Calling code
void TestTaskManagerL()
{
CTaskManager* taskManager = CTaskManager::NewLC();
// Add four tasks to the array
_LIT(KTaskName, "TASKX%u");
for (TInt index =0; index<4; index++)
{
TBuf<10> taskName;
taskName.Format(KTaskName, index); // Names each task
TTask* task = new (ELeave) TTask(taskName);
CleanupStack::PushL(task);
taskManager->AddTaskL(task);
CleanupStack::Pop(task); // Now owned by the taskManager array
}
ASSERT(4==taskManager->Count()); // Chapter 16 discusses ASSERTs
// Insert a task into element 3
_LIT(KNewTask, "InsertedTask");
TTask* insertedTask = new (ELeave) TTask(KNewTask);
CleanupStack::PushL(insertedTask);
taskManager->InsertTaskL(insertedTask, 3);
CleanupStack::Pop(insertedTask); // Now owned by taskManager
ASSERT(5==taskManager->Count());
// Delete a task
taskManager->DeleteTask(2);
ASSERT(4==taskManager->Count());
taskManager->RunAllTasksL();
// Destroys the array (which itself destroys the TTasks it owns)
CleanupStack::PopAndDestroy(taskManager);
}
四、RArray<T> and RPointerArray
class TTask // Basic T class, represents a task { public: TTask(const TDesC& aTaskName); void ExecuteTaskL() {}; // Omitted for clarity private: TBuf<10> iTaskName; }; TTask::TTask(const TDesC& aTaskName) { iTaskName.Copy(aTaskName); } // Holds a dynamic array of TTask pointers class CTaskManager : public CBase { public: static CTaskManager* NewLC(); ~CTaskManager(); public: void AddTaskL(TTask* aTask); void InsertTaskL(TTask* aTask, TInt aIndex); void RunAllTasksL(); void DeleteTask(TInt aIndex); public: inline TInt Count() {return (iTaskArray->Count());}; inline TTask* GetTask(TInt aIndex) {return(iTaskArray->At(aIndex));}; private: void ConstructL(); CTaskManager() {}; private: CArrayPtrSeg<TTask>* iTaskArray; }; const TInt KTaskArrayGranularity = 5; CTaskManager* CTaskManager::NewLC() { CTaskManager* me = new (ELeave) CTaskManager(); CleanupStack::PushL(me); me->ConstructL(); return (me); } CTaskManager::() {// Cleanup the array if (iTaskArray) iTaskArray->ResetAndDestroy(); // Destroys objects through ptrs delete iTaskArray; } void CTaskManager::ConstructL() { iTaskArray = new (ELeave) CArrayPtrSeg<TTask>(KTaskArrayGranularity); } void CTaskManager::AddTaskL(TTask* aTask) { // Add a task to the end of array // No need to check that aTask! =NULL because CBufBase does this // before appending it iTaskArray->AppendL(aTask); } void CTaskManager::InsertTaskL(TTask* aTask, TInt aIndex) { // Insert a task into a given element index // No assertion on aTask or aIndex because CArrayFixBase // and CBufBase do this iTaskArray->InsertL(aIndex, aTask); } void CTaskManager::RunAllTasksL() { // Iterates all TTask objects and calls ExecuteTaskL() TInt taskCount = iTaskArray->Count(); for (TInt index = 0; index < taskCount; index++) { (*iTaskArray)[index]->ExecuteTaskL(); } } void CTaskManager::DeleteTask(TInt aIndex) { // Removes the pointer from the array // The function stores a pointer to it so it can be destroyed TTask* task = iTaskArray->At(aIndex); if (task) { iTaskArray->Delete(aIndex); // Does not delete the object delete task; // Deletes the object } } // Calling code void TestTaskManagerL() { CTaskManager* taskManager = CTaskManager::NewLC(); // Add four tasks to the array _LIT(KTaskName, "TASKX%u"); for (TInt index =0; index<4; index++) { TBuf<10> taskName; taskName.Format(KTaskName, index); // Names each task TTask* task = new (ELeave) TTask(taskName); CleanupStack::PushL(task); taskManager->AddTaskL(task); CleanupStack::Pop(task); // Now owned by the taskManager array } ASSERT(4==taskManager->Count()); // Chapter 16 discusses ASSERTs // Insert a task into element 3 _LIT(KNewTask, "InsertedTask"); TTask* insertedTask = new (ELeave) TTask(KNewTask); CleanupStack::PushL(insertedTask); taskManager->InsertTaskL(insertedTask, 3); CleanupStack::Pop(insertedTask); // Now owned by taskManager ASSERT(5==taskManager->Count()); // Delete a task taskManager->DeleteTask(2); ASSERT(4==taskManager->Count()); taskManager->RunAllTasksL(); // Destroys the array (which itself destroys the TTasks it owns) CleanupStack::PopAndDestroy(taskManager); } 四、使用RArrayX 系列: RArray在调用结束后要调用Close 和 Reset 来清除。RArrray 可以存在 stack 也可以是在heap。 使用原则:尽量使用 RArray 而不是CArrayX,除非是要支持非连续存取和不同大小的对象的存取。 R 类的使用 class TTask // Basic T class, represents a task { public: TTask(const TDesC& aTaskName); void ExecuteTaskL() {}; // Omitted for clarity private: TBuf<10> iTaskName; }; TTask::TTask(const TDesC& aTaskName) { iTaskName.Copy(aTaskName); } /** * CTaskManager * */ class CTaskManager : public CBase { public: // Constructors and destructor /** * Destructor. */ ~CTaskManager(); /** * Two-phased constructor. */ static CTaskManager* NewL(); /** * Two-phased constructor. */ static CTaskManager* NewLC(); ~CCTaskManager(); public: void AddTaskL(TTask* aTask); void InsertTaskL(TTask* aTask, TInt aIndex); void RunAllTasksL(); void DeleteTask(TInt aIndex); public: inline TInt Count() {return (iTaskArray->Count());}; inline TTask* GetTask(TInt aIndex) {return(iTaskArray->At(aIndex));}; private: /** * Constructor for performing 1st stage construction */ CTaskManager() {} /** * EPOC default constructor for performing 2nd stage construction */ void ConstructL(); private: CArrayPtrSeg<TTask>* iTaskArray; }; #endif // TASKMANAGER_H class TTask // Basic T class, represents a task { public: TTask(const TDesC& aTaskName, const TInt aPriority); ... public: static TInt ComparePriorities(const TTask& aTask1, const TTask& aTask2); static TBool Match(const TTask& aTask1, const TTask& aTask2); private: TBuf<10> iTaskName; TInt iPriority; }; TTask::TTask(const TDesC& aTaskName, const TInt aPriority) : iPriority(aPriority){iTaskName.Copy(aTaskName);} // Returns 0 if both are equal priority, // Returns a negative value if aTask1 > aTask2 // Returns a positive value if aTask1 < aTask2 TInt TTask::ComparePriorities(const TTask& aTask1, const TTask& aTask2) { if (aTask1.iPriority>aTask2.iPriority) return (-1); else if (aTask1.iPriority<aTask2.iPriority) return (1); else return (0); } // Compares two tasks; returns ETrue if both iTaskName and // iPriority are identical TBool TTask::Match(const TTask& aTask1, const TTask& aTask2) { if ((aTask1.iPriority==aTask2.iPriority) && (aTask1.iTaskName.Compare(aTask2.iTaskName)==0)) { return (ETrue); } return (EFalse); } class CTaskManager : public CBase // Holds a dynamic array of TTask pointers { public: static CTaskManager* NewLC(); (); public: void AddTaskL(TTask& aTask); void InsertTaskL(TTask& aTask, TInt aIndex); void RunAllTasksL(); void DeleteTask(TInt aIndex); void DeleteTask(const TTask& aTask); public: inline TInt Count() {return (iTaskArray.Count());}; inline TTask& GetTask(TInt aIndex) {return(iTaskArray[aIndex]);}; private: CTaskManager() {}; private: RArray<TTask> iTaskArray; }; CTaskManager::() {// Close the array (free the memory associated with the entries) iTaskArray.Close(); } void CTaskManager::AddTaskL(TTask& aTask) {// Add a task to the end of array User::LeaveIfError(iTaskArray.Append(aTask)); } void CTaskManager::InsertTaskL(TTask& aTask, TInt aIndex) {// Insert a task in a given element User::LeaveIfError(iTaskArray.Insert(aTask, aIndex)); } void CTaskManager::RunAllTasksL() {// Sorts the tasks into priority order then iterates through them // and calls ExecuteTaskL() on each // Construct a temporary TLinearOrder object implicitly –the // equivalent of the following: // iTaskArray.Sort(TLinearOrder<TTask>(TTask::ComparePriorities)); iTaskArray.Sort(TTask::ComparePriorities); TInt taskCount = iTaskArray.Count(); for (TInt index = 0; index < taskCount; index++) { iTaskArray[index].ExecuteTaskL(); } } void CTaskManager::DeleteTask(const TTask& aTask) {// Removes all tasks identical to aTask from the array // Constructs a temporary TIdentityRelation object implicitly –the // equivalent of the following: // TInt foundIndex = iTaskArray.Find(aTask, // TIdentityRelation<TTask>(TTask::Match)); while (TInt foundIndex = iTaskArray.Find(aTask, TTask::Match)! =KErrNotFound) { iTaskArray.Remove(foundIndex); } } void CTaskManager::DeleteTask(TInt aIndex) {// Removes the task at index aIndex from the array iTaskArray.Remove(aIndex); } void TestTaskManagerL() { CTaskManager* taskManager = CTaskManager::NewLC(); // Add tasks to the array, use the index to set the task priority _LIT(KTaskName, "TASKX%u"); for (TInt index=0; index<4; index++) { TBuf<10> taskName; taskName.Format(KTaskName, index); TTask task(taskName, index); taskManager->AddTaskL(task); } ASSERT(4==taskManager->Count()); // Add a copy of the task at index 2 // to demonstrate sorting and matching TBuf<10> taskName; taskName.Format(KTaskName, 2); TTask copyTask(taskName, 2); taskManager->AddTaskL(copyTask); ASSERT(5==taskManager->Count()); taskManager->RunAllTasksL(); // Remove both copies of the task taskManager->DeleteTask(copyTask); ASSERT(3==taskManager->Count()); // Destroy the taskManager CleanupStack::PopAndDestroy(taskManager); }
五、内置的字符串向量 CPtrCArray, CDesCArray, CDesCArrayFlat, CDesCArraySeg 六、固定元素个数组类 TFixedArray,当元素个数是固定个数的时候,应该使用TFixedArray. class TTask { public: TTask(TInt aPriority); public: TInt iPriority; }; TTask::TTask(TInt aPriority) : iPriority(aPriority){} void TestFixedArray() { TTask tasks[5]={TTask(0), TTask(1), TTask(2), TTask(3), TTask(4)}; // Wrap tasks with a range-checked TFixedArray TFixedArray<TTask, 5> taskArray(&tasks[0], 5); taskArray[1].iPriority = 3; // change priority taskArray[5].iPriority = 3; // Assertion fails -> panics debug builds (USER 133) taskArray.At(5).iPriority = 3; // Assertion fails -> panics debug & release builds } 七、存二进制数据的向量 CBufFlat 和 CBufSeg,存取二进制文件,可以动态分配大小; // Returns random data in an 8-bit heap descriptor of length = aLength HBufC8* GetRandomDataLC(TInt aLength); // Defined elsewhere void PrintBufferL(CBufBase* aBuffer) { aBuffer->Compress(); // Compress to free unused memory at the end of a segment TInt length = aBuffer->Size(); HBufC8* readBuf = HBufC8::NewL(length); TPtr8 writable(readBuf->Des()); aBuffer->Read(0, writable); ... // Omitted. Print to the console delete readBuf; } void TestBuffersL() { __UHEAP_MARK; // Heap checking macro to test for memory leaks CBufBase* buffer = CBufSeg::NewL(16); // Granularity = 16 CleanupStack::PushL(buffer); // There is no NewLC() function HBufC8* data = GetRandomDataLC(32);// Data is on the cleanup stack buffer->InsertL(0, *data); // Destroy original. A copy is now stored in the buffer CleanupStack::PopAndDestroy(data); PrintBufferL(buffer); buffer->ExpandL(0, 100); // Pre-expand the buffer TInt pos = 0; for (TInt index = 0; index <4; index++, pos+16) {// Write the data in several chunks data = GetRandomDataLC(16); buffer->Write(pos, *data); CleanupStack::PopAndDestroy(data); // Copied so destroy here } PrintBufferL(buffer); CleanupStack::PopAndDestroy(buffer); // Clean up the buffer __UHEAP_MARKEND; // End of heap checking }