Click here to Skip to main content
15,885,032 members
Articles / Programming Languages / C++
Article

A better memory managed MFC CArray

Rate me:
Please Sign up or sign in to vote.
2.44/5 (5 votes)
17 Mar 2002CPOL3 min read 135.4K   1.1K   24   14
A more heap-friendly template CArray using a memory pool

Introduction

When I used MFC's CArray in one of my projects, I found it's not very heap-friendly.

It does use a pre-allocated memory pool but it doesn't use it clearly. For example, it doesn't have a constructor that allow us to explicitly declare the size of our pre-allocated memory pool. Furthermore, I think MFC CArray doesn't make clear between the actual memory pool size and the elements size of the array.

And if we really need to "pre-allocate", we has to make use of its grow-by variable, which is unclear and confusing.

How to use

Include the two files NewBValArray.h and NewBConfig.h in your project

Declare a variable:

#include "NewBValArray.h"
NewBValArray<MyClass,MyClass> rgMyArray(1000);

So rgMyArray will pre-allocate a memory pool of 1000 MyClass items.

NOTE: rgMyArray is still a blank array, i.e rgMyArray.GetSize() = 0; as long as you don't "add" items to it through Add(), or oprerator[].

Otherwise, it can be used the same as MFC's CArray, i.e you can safely replace all CArray with NewBArray.

Why don't I use MFC CArray?

After my posting, many ask me why I didn't use MFC's CArray?

I do know that MFC CArray can pre-allocate memory. But it really doesn't work as I expect.

What do I expect? I'd like to separate the holder (memory) and the meaning of array elements. That means I'll allocate a big chunk of memory to hold the elements' data. This memory should be allocated in the array's ctor and delete at array's dtor. During its lifetime, this part of memory shouldn't be changed

Now let's dive into the MFC CArray source code. It's contains 4 variables:

TYPE* m_pData;   // the actual array of data 
int m_nSize;     // # of elements (upperBound - 1)
int m_nMaxSize;  // max allocated
int m_nGrowBy;   // grow amount

Now, let see how can we force CArray to pre-allocate memory by SetSize(int nNewSize, int nGrowBy). nNewSise is the new desired size. nGrowBy I'll explain later. Then assume that we have

CArray<MyClass,MyClass> rgMFCArray;

What if I do this:

rgMFCArray.SetSize(1000,0);

Now I expect that rgMFCArray has 1000 pre-allocated spaces for MyClass, means I can Add to it 1000 MyClass variables. But actually rgMFCArray now contains 1000 MyClass "default" variables and if I call rgMFCArray.Add(...) then the m_pData will need to reallocate to a 1001 MyClass space : not what I expect.

Again, what if I do this:

rgMFCArray.SetSize(0,1000);

Now I make use of the grow-by stuff. At this time rgMFCArray will assign its m_nGrowBy = 1000. That's all! No allocation of memory. So if you do rgMFCArray[1], you'll get ASSERT false.

Then what if:

rgMFCArray.Add(someMyClassvariable);

Yeah, this time it's worked. Now CArray will allocate a memory chunk of size 1000*sizeof(MyClass). So if I really like to make use of pre-allocate memory on MFC's CArray, I have to use its m_nGrowBy variable. So confusing!

More! MFC's Array doesn't provide you any method to "remove" all CArray elements or change its memory allocation.

You can ask me about CArray::RemoveAll(). This method will remove all array elements plus deallocate its memory.

But really,we can remove all elements of MFC CArray with a long statement

for (int i = rgMFCArray.GetCount() - 1; i >= 0 ; i --)
   rgMFCArray.RemoveAt(i)

Again, it make me confused and uneasy.

So that's why I rewrite my own array class by just "hacking" MFC's CArray source, cause really MFC CArray is still a good boy, especially its making use of placement new and delete.

In my new class, I explicitly separate m_nSize (number of elements) and m_nMaxSize (the size of pre-allocated memory pool). I added a ctor that has one parameter to declare the size of pre-allocated memory, and this memory I can take from my own allocator as in many projects. And the method RemoveAll() just effectively "removes" the elements, i.e calls their dtor but leaves the memory pool untouched. This memory pool will be cleaned at NewBArray's dtor. Moreover, I still keep the ability to "grow" the memory pool to a larger one if the user adds more elements the array capacity. But this action shouldn't happen because it makes the heap fragment and cause memory allocation, and copy overhead.

This code is written by Nguyen Binh. I greatly appreciate any feedback.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralBug fix Pin
merckel22-May-05 19:47
merckel22-May-05 19:47 
GeneralWhy not use CMyTypedPtrList Pin
Simon Hughes24-Mar-02 22:47
Simon Hughes24-Mar-02 22:47 
Have a look at http://www.codeproject.com/cpp/smartlist.asp

Regards,
Simon Hughes
E-mail: simon@hicrest.net
Web: www.hicrest.net
GeneralPurpose of CArray Pin
Zac Howland20-Mar-02 4:48
Zac Howland20-Mar-02 4:48 
GeneralRe: Purpose of CArray Pin
Nguyen Binh22-Mar-02 17:55
Nguyen Binh22-Mar-02 17:55 
QuestionWhy not using CArray::SetSize? Pin
Ingo Kellpinski18-Mar-02 3:10
Ingo Kellpinski18-Mar-02 3:10 
AnswerRe: Why not using CArray::SetSize? Pin
Nguyen Binh18-Mar-02 16:34
Nguyen Binh18-Mar-02 16:34 
GeneralRe: Why not using CArray::SetSize? Pin
Bernhard18-Mar-02 22:28
Bernhard18-Mar-02 22:28 
GeneralRe: Why not using CArray::SetSize? Pin
Jörgen Sigvardsson18-Mar-02 23:10
Jörgen Sigvardsson18-Mar-02 23:10 
GeneralRe: Why not using CArray::SetSize? Pin
Bernhard18-Mar-02 23:19
Bernhard18-Mar-02 23:19 
GeneralRe: Why not using CArray::SetSize? Pin
Jörgen Sigvardsson18-Mar-02 23:25
Jörgen Sigvardsson18-Mar-02 23:25 
GeneralRe: Why not using CArray::SetSize? Pin
Bernhard18-Mar-02 23:39
Bernhard18-Mar-02 23:39 
AnswerRe: Why not using CArray::SetSize? Pin
Christian Graus18-Mar-02 23:35
protectorChristian Graus18-Mar-02 23:35 
GeneralRe: Why not using CArray::SetSize? Pin
Nguyen Binh19-Mar-02 0:15
Nguyen Binh19-Mar-02 0:15 
GeneralRe: Why not using CArray::SetSize? Pin
Christian Graus19-Mar-02 0:28
protectorChristian Graus19-Mar-02 0:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.