CArray Class

Supports arrays that are like C arrays, but can dynamically reduce and grow as necessary.

Syntax

template <class TYPE, class ARG_TYPE = const TYPE&>
class CArray : public CObject

Parameters

TYPE
Template parameter that specifies the type of objects stored in the array. TYPE is a parameter that is returned by CArray.

ARG_TYPE
Template parameter that specifies the argument type that is used to access objects stored in the array. Often a reference to TYPE. ARG_TYPE is a parameter that is passed to CArray.

Members

Public Constructors

Name Description
CArray::CArray Constructs an empty array.

Public Methods

Name Description
CArray::Add Adds an element to the end of the array; grows the array if necessary.
CArray::Append Appends another array to the array; grows the array if necessary
CArray::Copy Copies another array to the array; grows the array if necessary.
CArray::ElementAt Returns a temporary reference to the element pointer within the array.
CArray::FreeExtra Frees all unused memory above the current upper bound.
CArray::GetAt Returns the value at a given index.
CArray::GetCount Gets the number of elements in this array.
CArray::GetData Allows access to elements in the array. Can be NULL.
CArray::GetSize Gets the number of elements in this array.
CArray::GetUpperBound Returns the largest valid index.
CArray::InsertAt Inserts an element (or all the elements in another array) at a specified index.
CArray::IsEmpty Determines whether the array is empty.
CArray::RemoveAll Removes all the elements from this array.
CArray::RemoveAt Removes an element at a specific index.
CArray::SetAt Sets the value for a given index; array not allowed to grow.
CArray::SetAtGrow Sets the value for a given index; grows the array if necessary.
CArray::SetSize Sets the number of elements to be contained in this array.

Public Operators

Name Description
operator[] Sets or gets the element at the specified index.

Remarks

Array indexes always start at position 0. You can decide whether to fix the upper bound or enable the array to expand when you add elements past the current bound. Memory is allocated contiguously to the upper bound, even if some elements are null.

Note

Most methods that resize a CArray object or add elements to it use memcpy_s to move elements. This is a problem because memcpy_s is not compatible with any objects that require the constructor to be called. If the items in the CArray are not compatible with memcpy_s, you must create a new CArray of the appropriate size. You must then use CArray::Copy and CArray::SetAt to populate the new array because those methods use an assignment operator instead of memcpy_s.

As with a C array, the access time for a CArray indexed element is constant and is independent of the array size.

Tip

Before using an array, use SetSize to establish its size and allocate memory for it. If you do not use SetSize, adding elements to your array causes it to be frequently reallocated and copied. Frequent reallocation and copying are inefficient and can fragment memory.

If you need a dump of individual elements in an array, you must set the depth of the CDumpContext object to 1 or larger.

Certain member functions of this class call global helper functions that must be customized for most uses of the CArray class. See the topic Collection Class Helpers in the MFC Macros and Globals section.

Array class derivation is like list derivation.

For more information about how to use CArray, see the article Collections.

Inheritance Hierarchy

CObject

CArray

Requirements

Header: afxtempl.h

CArray::Add

Adds a new element to the end of an array, growing the array by 1.

INT_PTR Add(ARG_TYPE newElement);

Parameters

ARG_TYPE
Template parameter specifying the type of arguments referencing elements in this array.

newElement
The element to be added to this array.

Return Value

The index of the added element.

Remarks

If SetSize has been used with an nGrowBy value greater than 1, then extra memory may be allocated. However, the upper bound will increase by only 1.

Example

// example for CArray::Add
CArray<CPoint, CPoint> ptArray;

CPoint pt(10, 20);
ptArray.Add(pt);             // Element 0
ptArray.Add(CPoint(30, 40)); // Element 1

CArray::Append

Call this member function to add the contents of one array to the end of another.

INT_PTR Append(const CArray& src);

Parameters

src
Source of the elements to be appended to an array.

Return Value

The index of the first appended element.

Remarks

The arrays must be of the same type.

If necessary, Append may allocate extra memory to accommodate the elements appended to the array.

Example

CArray<CPoint, CPoint> myArray1, myArray2;

// Add elements to the second array.
myArray2.Add(CPoint(11, 22));
myArray2.Add(CPoint(12, 42));

// Add elements to the first array and also append the second array.
myArray1.Add(CPoint(1, 2));
myArray1.Append(myArray2);

CArray::CArray

Constructs an empty array.

CArray();

Remarks

The array grows one element at a time.

Example

CArray<CPoint, CPoint> ptArray;

CArray::Copy

Use this member function to copy the elements of one array to another.

void Copy(const CArray& src);

Parameters

src
Source of the elements to be copied to an array.

Remarks

Call this member function to overwrite the elements of one array with the elements of another array.

Copy does not free memory; however, if necessary, Copy may allocate extra memory to accommodate the elements copied to the array.

Example

CArray<CPoint, CPoint> myArray1, myArray2;

// Add elements to the second array.
myArray2.Add(CPoint(11, 22));
myArray2.Add(CPoint(12, 42));

// Copy the elements from the second array to the first.
myArray1.Copy(myArray2);

CArray::ElementAt

Returns a temporary reference to the specified element within the array.

TYPE& ElementAt(INT_PTR nIndex);
const TYPE& ElementAt(INT_PTR nIndex) const;

Parameters

nIndex
An integer index that is greater than or equal to 0 and less than or equal to the value returned by GetUpperBound.

Return Value

A reference to an array element.

Remarks

It is used to implement the left-side assignment operator for arrays.

Example

See the example for GetSize.

CArray::FreeExtra

Frees any extra memory that was allocated while the array was grown.

void FreeExtra();

Remarks

This function has no effect on the size or upper bound of the array.

Example

See the example for GetData.

CArray::GetAt

Returns the array element at the specified index.

TYPE& GetAt(INT_PTR nIndex);
const TYPE& GetAt(INT_PTR nIndex) const;

Parameters

TYPE
Template parameter specifying the type of the array elements.

nIndex
An integer index that is greater than or equal to 0 and less than or equal to the value returned by GetUpperBound.

Return Value

The array element currently at this index.

Remarks

Passing a negative value or a value greater than the value returned by GetUpperBound will result in a failed assertion.

Example

CArray<CPoint, CPoint> myArray;
CPoint pt;

// Add elements to the array.
for (int i = 0; i < 10; i++)
{
   myArray.Add(CPoint(i, 2 * i));
}

// Modify all the points in the array.
for (int i = 0; i <= myArray.GetUpperBound(); i++)
{
   pt = myArray.GetAt(i);
   pt.x = 0;
   myArray.SetAt(i, pt);
}

CArray::GetCount

Returns the number of array elements.

INT_PTR GetCount() const;

Return Value

The number of items in the array.

Remarks

Call this method to retrieve the number of elements in the array. Because indexes are zero-based, the size is 1 greater than the largest index. Calling this method will generate the same result as the CArray::GetSize method.

Example

CArray<CPoint, CPoint> myArray;

// Add elements to the array.
for (int i = 0; i < 10; i++)
   myArray.Add(CPoint(i, 2 * i));

// Modify all the points in the array.
for (int i = 0; i < myArray.GetCount(); i++)
{
   CPoint &pt = myArray.ElementAt(i);
   pt.x = 0;
}

CArray::GetData

Use this member function to gain direct access to the elements in an array.

const TYPE* GetData() const;
TYPE* GetData();

Parameters

TYPE
Template parameter specifying the type of the array elements.

Return Value

A pointer to an array element.

Remarks

If no elements are available, GetData returns a null value.

While direct access to the elements of an array can help you work more quickly, use caution when calling GetData; any errors you make directly affect the elements of your array.

Example

CArray<CPoint, CPoint> myArray;

// Allocate memory for at least 32 elements.
myArray.SetSize(32, 128);

// Add elements to the array.
CPoint *pPt = (CPoint *)myArray.GetData();
for (int i = 0; i < 32; i++, pPt++)
{
   *pPt = CPoint(i, 2 * i);
}

// Only keep first 5 elements and free extra (unused) bytes.
myArray.SetSize(5, 128);
myArray.FreeExtra();

#if _DEBUG
afxDump.SetDepth(1);
afxDump << "myArray: " << &myArray << "\n";
#endif

CArray::GetSize

Returns the size of the array.

INT_PTR GetSize() const;

Remarks

Because indexes are zero-based, the size is 1 greater than the largest index. Calling this method will generate the same result as the CArray::GetCount method.

Example

CArray<CPoint, CPoint> myArray;

// Add elements to the array.
for (int i = 0; i < 10; i++)
   myArray.Add(CPoint(i, 2 * i));

// Modify all the points in the array.
for (int i = 0; i < myArray.GetSize(); i++)
{
   CPoint &pt = myArray.ElementAt(i);
   pt.x = 0;
}

CArray::GetUpperBound

Returns the current upper bound of this array.

INT_PTR GetUpperBound() const;

Remarks

Because array indexes are zero-based, this function returns a value 1 less than GetSize.

The condition GetUpperBound( ) = -1 indicates that the array contains no elements.

Example

See the example for CArray::GetAt.

CArray::InsertAt

The first version of InsertAt inserts one element (or multiple copies of an element) at a specified index in an array.

void InsertAt(
    INT_PTR nIndex,
    ARG_TYPE newElement,
    INT_PTR nCount = 1);

void InsertAt(
    INT_PTR nStartIndex,
    CArray* pNewArray);

Parameters

nIndex
An integer index that may be greater than the value returned by GetUpperBound.

ARG_TYPE
Template parameter specifying the type of elements in this array.

newElement
The element to be placed in this array.

nCount
The number of times this element should be inserted (defaults to 1).

nStartIndex
An integer index that may be greater than the value returned by GetUpperBound.

pNewArray
Another array that contains elements to be added to this array.

Remarks

In the process, it shifts up (by incrementing the index) the existing element at this index, and it shifts up all the elements above it.

The second version inserts all the elements from another CArray collection, starting at the nStartIndex position.

The SetAt function, in contrast, replaces one specified array element and does not shift any elements.

Example

// example for CArray::InsertAt

CArray<CPoint, CPoint> ptArray;

ptArray.Add(CPoint(10, 20));         // Element 0
ptArray.Add(CPoint(30, 40));         // Element 1 (will become element 2)
ptArray.InsertAt(1, CPoint(50, 60)); // New element 1

CArray::IsEmpty

Determines whether the array is empty.

BOOL IsEmpty() const;

Return Value

Nonzero if the array contains no elements; otherwise 0.

CArray::operator []

These subscript operators are a convenient substitute for the SetAt and GetAt functions.

TYPE& operator[](int_ptr nindex);
const TYPE& operator[](int_ptr nindex) const;

Parameters

TYPE
Template parameter specifying the type of elements in this array.

nIndex
Index of the element to be accessed.

Remarks

The first operator, called for arrays that are not const, may be used on either the right (r-value) or the left (l-value) of an assignment statement. The second, called for const arrays, may be used only on the right.

The Debug version of the library asserts if the subscript (either on the left or right side of an assignment statement) is out of bounds.

Example

CArray<CPoint, CPoint> myArray;

// Add elements to the array.
for (int i = 0; i < 10; i++)
{
   myArray.Add(CPoint(i, 2 * i));
}

// Modify all the points in the array.
for (int i = 0; i <= myArray.GetUpperBound(); i++)
{
   myArray[i].x = 0;
}

CArray::RelocateElements

Relocates data to a new buffer when the array should grow or shrink.

template<class TYPE, class ARG_TYPE>
AFX_INLINE void CArray<TYPE, ARG_TYPE>::RelocateElements(
    TYPE* pNewData,
    const TYPE* pData,
    INT_PTR nCount);

Parameters

pNewData
A new buffer for the array of elements.

pData
The old array of elements.

nCount
Number of elements in the old array.

Remarks

pNewData is always large enough to hold all the pData elements.

The CArray implementation uses this method to copy the old data to a new buffer when the array should grow or shrink (when SetSize or FreeExtra are called). The default implementation just copies the data.

For arrays in which an element contains a pointer to one of its own members, or another structure contains a pointer to one of the array elements, the pointers are not updated in plain copy. In this case, you can correct pointers by implementing a specialization of RelocateElements with the relevant types. You are also responsible for data copying.

CArray::RemoveAll

Removes all the elements from this array.

void RemoveAll();

Remarks

If the array is already empty, the function still works.

Example

CArray<CPoint, CPoint> myArray;

// Add elements to the array.
for (int i = 0; i < 10; i++)
   myArray.Add(CPoint(i, 2 * i));

myArray.RemoveAll();

#ifdef _DEBUG
afxDump.SetDepth(1);
afxDump << "myArray: " << &myArray << "\n";
#endif

CArray::RemoveAt

Removes one or more elements starting at a specified index in an array.

void RemoveAt(
    INT_PTR nIndex,
    INT_PTR nCount = 1);

Parameters

nIndex
An integer index that is greater than or equal to 0 and less than or equal to the value returned by GetUpperBound.

nCount
The number of elements to remove.

Remarks

In the process, it shifts down all the elements above the removed element(s). It decrements the upper bound of the array but does not free memory.

If you try to remove more elements than are contained in the array above the removal point, then the Debug version of the library asserts.

Example

CArray<CPoint, CPoint> myArray;

// Add elements to the array.
for (int i = 0; i < 10; i++)
{
   myArray.Add(CPoint(i, 2 * i));
}

myArray.RemoveAt(5);

#ifdef _DEBUG
afxDump.SetDepth(1);
afxDump << "myArray: " << &myArray << "\n";
#endif

CArray::SetAt

Sets the array element at the specified index.

void SetAt(INT_PTR nIndex, ARG_TYPE newElement);

Parameters

nIndex
An integer index that is greater than or equal to 0 and less than or equal to the value returned by GetUpperBound.

ARG_TYPE
Template parameter specifying the type of arguments used for referencing array elements.

newElement
The new element value to be stored at the specified position.

Remarks

SetAt will not cause the array to grow. Use SetAtGrow if you want the array to grow automatically.

You must ensure that your index value represents a valid position in the array. If it is out of bounds, then the Debug version of the library asserts.

Example

See the example for GetAt.

CArray::SetAtGrow

Sets the array element at the specified index.

void SetAtGrow(INT_PTR nIndex, ARG_TYPE newElement);

Parameters

nIndex
An integer index that is greater than or equal to 0.

ARG_TYPE
Template parameter specifying the type of elements in the array.

newElement
The element to be added to this array. A NULL value is allowed.

Remarks

The array grows automatically if necessary (that is, the upper bound is adjusted to accommodate the new element).

Example

// example for CArray::SetAtGrow
CArray<CPoint, CPoint> ptArray;

ptArray.Add(CPoint(10, 20)); // Element 0
ptArray.Add(CPoint(30, 40)); // Element 1
// Element 2 deliberately skipped
ptArray.SetAtGrow(3, CPoint(50, 60)); // Element 3

CArray::SetSize

Establishes the size of an empty or existing array; allocates memory if necessary.

void SetSize(
    INT_PTR nNewSize,
    INT_PTR nGrowBy = -1);

Parameters

nNewSize
The new array size (number of elements). Must be greater than or equal to 0.

nGrowBy
The minimum number of element slots to allocate if a size increase is necessary.

Remarks

If the new size is smaller than the old size, then the array is truncated and all unused memory is released.

Use this function to set the size of your array before you begin using the array. If you do not use SetSize, adding elements to your array causes it to be frequently reallocated and copied. Frequent reallocation and copying are inefficient and can fragment memory.

The nGrowBy parameter affects internal memory allocation while the array is growing. Its use never affects the array size as reported by GetSize and GetUpperBound. If the default value is used, MFC allocates memory in a way calculated to avoid memory fragmentation and optimize efficiency for most cases.

Example

See the example for GetData.

See also

MFC Sample COLLECT
CObject Class
Hierarchy Chart
CObArray Class
Collection Class Helpers