Click here to Skip to main content
11,646,594 members (65,829 online)
Click here to Skip to main content

CArray: A simple but highly efficient improvement

, 24 Jan 2000 205.9K 1.4K 34
Rate this:
Please Sign up or sign in to vote.
A simple derived template class that can boost the efficiency of your programs.

Introduction

If you use CArray, and the const keyword, your programs might be running 50% too slow! Interested? Well read on...

Background

I love Object-Oriented programming. And after 15 years of writing C programs, I'd be quite happy to code in C++ forever.

Two of the things I love most are: templates and the const keyword.

If you're like me, you use const everywhere. It encapsulates encapsulation. Well kind of... Anyway, if I can pass a const reference or const pointer, I will. Why? Because it means that my calling routine knows that its data is safe. It reduces complexity.

Templates speak for themselves. Well actually, they don't...and the syntax sucks (I have to race to a text book every time I want to create a template - that either means the syntax sucks or I'm stupid or maybe I just drink too much red wine...).

Anyway, Microsoft has written several useful template classes, including CArray. It's a pity they did such a poor job, particularly with the documentation.

What's wrong with CArray?

I've been burned by CArray several times. My code works fine, but then I discover a whole lot of unnecessary copying going on.

CArray is fine for arrays of ints and doubles, but give it a class with more than a few bytes of data, and your program's efficiency gets clobbered.

Here's the kind of thing I like to do:

 //
 // Declare a useful class.
 //
class MyClass
{
protected:
    // data here (maybe lots)
public:
    // etc. etc. etc. etc
};

typedef CArray<MyClass,MyClass&> MyClassArray;

Then, I'll use this array as follows:

MyFunction(const MyClassArray& array)
{
    for (int ii = 0 ; ii < array.GetSize() ; ii++)
        DoSomething(array[ii]);
}
DoSomething(const MyClass& my_object)
{
    // do stuff here
}

Pretty simple, right? But with CArray, the call to DoSomething(array[ii]) creates a temporary copy of the array element (in this case, MyClass) before calling DoSomething! Then the temporary copy is destroyed before the next loop iteration.

If my array element is an int, that's fine by me. But if it's a class with 1K of data, then CArray is silently stabbing me in the back.

Of course, to be fair, CArray isn't "silent". Its operator[] const and GetAt methods are documented to return a copy.

But WHY?

I can't think of any good reason (unless CArray is only designed for arrays of ints etc.) why these methods return a copy. They should return a const reference.

After getting burned for the Nth time, I've done something about it.

The Solution

I've made a simple derivation of the template class CArray, called OCArray (OC stands for Open Concepts - one of my companies). Or, if you like, it can mean "Optimised-CArray".

/*
 * Template Class: OCArray
 * Author: Russell Robinson
 * Purpose:
 *    To provide a generic array class like CArray without the problems.
 *    OCArray takes one parameter - TYPE.  Unlike CArray, OCArray always
 *    returns references and expects references as parameters.
 */
template <class TYPE> class OCArray : public CArray<TYPE,TYPE&>
{
public:
    /*
     * Method: OCArray::operator[] const
     * Parameters: i_index the array index to access
     * Returns: const TYPE& reference to the element at the index
     * Author: Russell Robinson
     * Purpose:
     *    To return an element of the array for const access.
     */
    inline const TYPE&    operator[](int i_index) const
    {
        ASSERT(0 <= i_index && i_index < GetSize());
        return (GetData()[i_index]);
    };

    /*
     * Method: OCArray::GetAt
     * Parameters: i_index the array index to access
     * Returns: const TYPE& reference to the element at the index
     * Author: Russell Robinson
     * Purpose:
     *    To return an element of the array for const access.
     */
    inline const TYPE&    GetAt(int i_index) const
    {
        ASSERT(0 <= i_index && i_index < GetSize());
        return (GetData()[i_index]);
    };

    /*
     * Method: OCArray::operator[]
     * Parameters: i_index the array index to access
     * Returns: TYPE& reference to the element at the index
     * Author: Russell Robinson
     * Purpose:
     *    To return an element of the array for possible modification.
     *    This method is needed because the compiler
     *    loses the base class's method.
     */
    inline TYPE& operator[](int i_index)
    {
        ASSERT(0 <= i_index && i_index < GetSize());
        return (GetData()[i_index]);
    };
};

Just use OCArray instead of CArray. It only takes one parameter, because the argument type is implied as being a reference. This also helps remind you that you're not using CArray.

The result is that there is no copying when you access the array through a const reference or pointer.

The time saving is around 50% in an optimized program, and can be 75% in a debug version!

The above is all you need, but I've provided a demonstration project so that you can see the difference.

Now we can think about what we'll do with all those spare CPU cycles......

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Russell Robinson
Web Developer
Australia Australia
Started programming in 1978 using UNIX on a DEC PDP 11/70. Initially self-taught, but completed BSc at University of NSW (Major in Computer Science) in 1981.

Experienced in UNIX kernel work, compilers, language design, hardware control, and many other areas. Lots of languages but really loves C++.

Currently developing and marketing a product called TTMaker - advanced scheduling software.

Good customer service is #1 priority. So, very unimpressed with Microsoft's attitude.

You may also be interested in...

Comments and Discussions

 
GeneralMy vote of 5 Pin
MarSal7714-May-13 22:40
memberMarSal7714-May-13 22:40 
QuestionIs CArray Derivable? Pin
My2Cents3-Jan-09 15:14
memberMy2Cents3-Jan-09 15:14 
Questionabout change an index [modified] Pin
eantaru16-Apr-07 22:02
membereantaru16-Apr-07 22:02 
Generaldifference between CArray and CArray Pin
Ilana Melnik19-Mar-07 3:50
memberIlana Melnik19-Mar-07 3:50 
GeneralRe: difference between CArray and CArray Pin
Pandele Florin2-Feb-10 1:09
memberPandele Florin2-Feb-10 1:09 
QuestionCArray in CArray.. Doesn't it work?? Pin
microprocessor3-Nov-06 23:39
membermicroprocessor3-Nov-06 23:39 
Generalchanges in Visual 2003 and 2005 Pin
Bernard Deleg31-Oct-06 4:09
memberBernard Deleg31-Oct-06 4:09 
GeneralSerialization of CArray Pin
murtazadhari31-Aug-06 9:36
membermurtazadhari31-Aug-06 9:36 
GeneralOCAssert links Pin
Russell Robinson15-Feb-06 11:22
memberRussell Robinson15-Feb-06 11:22 
Generalstd::vector Pin
Christian Graus1-Sep-05 18:14
memberChristian Graus1-Sep-05 18:14 
GeneralRe: std::vector Pin
Anonymous2-Sep-05 13:41
sussAnonymous2-Sep-05 13:41 
GeneralRe: std::vector Pin
Christian Graus4-Sep-05 10:27
memberChristian Graus4-Sep-05 10:27 
Questionwhy did you use ElementAt? Pin
jiaguangwei1-Sep-05 17:59
sussjiaguangwei1-Sep-05 17:59 
AnswerRe: why did you use ElementAt? Pin
Russell Robinson2-Sep-05 13:45
memberRussell Robinson2-Sep-05 13:45 
QuestionWhy not STL vector? Pin
Anthony_Yio24-Feb-03 15:11
memberAnthony_Yio24-Feb-03 15:11 
AnswerYou're right Pin
Jonathan de Halleux10-Apr-03 3:08
memberJonathan de Halleux10-Apr-03 3:08 
GeneralInsertAt problem Pin
Paul129-Jul-02 10:38
sussPaul129-Jul-02 10:38 
GeneralRe: InsertAt problem Pin
Russell Robinson29-Jul-02 17:40
memberRussell Robinson29-Jul-02 17:40 
GeneralRe: InsertAt problem Pin
Paul130-Jul-02 8:58
memberPaul130-Jul-02 8:58 
GeneralRe: InsertAt problem Pin
Paul131-Jul-02 8:10
sussPaul131-Jul-02 8:10 
GeneralRe: InsertAt problem Pin
Russell Robinson31-Jul-02 9:48
memberRussell Robinson31-Jul-02 9:48 
GeneralRe: InsertAt problem Pin
Russell Robinson31-Jul-02 9:45
memberRussell Robinson31-Jul-02 9:45 
GeneralRe: InsertAt problem Pin
Paul131-Jul-02 11:10
sussPaul131-Jul-02 11:10 
GeneralRe: InsertAt problem Pin
Russell Robinson1-Aug-02 14:30
memberRussell Robinson1-Aug-02 14:30 
GeneralRe: InsertAt problem Pin
Nguyen Binh5-Apr-03 4:13
memberNguyen Binh5-Apr-03 4:13 
GeneralRe: InsertAt problem Pin
NDC394847315-Feb-06 10:02
memberNDC394847315-Feb-06 10:02 
GeneralRe: InsertAt problem Pin
Russell Robinson15-Feb-06 11:22
memberRussell Robinson15-Feb-06 11:22 
Question2d implementation? Pin
Nitron12-Jul-02 3:51
memberNitron12-Jul-02 3:51 
AnswerRe: 2d implementation? Pin
Russell Robinson16-Jul-02 22:29
memberRussell Robinson16-Jul-02 22:29 
Generalreason why GetAt is not returning a const Pin
Sergey Zabelin6-May-02 14:37
memberSergey Zabelin6-May-02 14:37 
GeneralRe: reason why GetAt is not returning a const Pin
Russell Robinson6-May-02 16:39
memberRussell Robinson6-May-02 16:39 
GeneralI have used the component, thank Pin
John Wong27-Sep-02 8:48
memberJohn Wong27-Sep-02 8:48 
GeneralFixed on MFC 7.0!!! Pin
Nguyen Binh20-Mar-02 16:47
memberNguyen Binh20-Mar-02 16:47 
GeneralRe: Fixed on MFC 7.0!!! Pin
Brian Delahunty30-Jun-02 11:36
editorBrian Delahunty30-Jun-02 11:36 
GeneralMaybe I'm wrong but... Pin
Gleason5-Jan-02 19:00
memberGleason5-Jan-02 19:00 
GeneralRe: Maybe I'm wrong but... Pin
Russell Robinson5-Jan-02 19:09
memberRussell Robinson5-Jan-02 19:09 
Generalasengupt@uiuc.edu Pin
Ananya Sen Gupta27-Jun-01 11:00
memberAnanya Sen Gupta27-Jun-01 11:00 
GeneralRe: Question ... Pin
Alexander Berthold16-Oct-01 1:08
memberAlexander Berthold16-Oct-01 1:08 
GeneralURGENT : It doesn't work for me Pin
Sylvie22-May-01 23:30
memberSylvie22-May-01 23:30 
GeneralRe: URGENT : It doesn't work for me Pin
Russell Robinson23-May-01 13:21
memberRussell Robinson23-May-01 13:21 
GeneralRight AND wrong Pin
PhartPhace17-Sep-00 14:08
sussPhartPhace17-Sep-00 14:08 
GeneralRe: Right AND wrong Pin
Russell Robinson17-Sep-00 14:23
sussRussell Robinson17-Sep-00 14:23 
GeneralThe same problem with CMap and CList Pin
Thales P. Carvalho4-Jul-00 23:18
sussThales P. Carvalho4-Jul-00 23:18 
GeneralThe same problem with CMap and CList Pin
Thales P. Carvalho4-Jul-00 23:16
sussThales P. Carvalho4-Jul-00 23:16 
GeneralRe: The same problem with CMap and CList Pin
Russell Robinson4-Jul-00 23:30
sussRussell Robinson4-Jul-00 23:30 
GeneralAnother idea which gets rid of the problem of having to write a new class Pin
PJ Naughter26-Jan-00 8:45
sussPJ Naughter26-Jan-00 8:45 
GeneralRe: Another idea which gets rid of the problem of having to write a new class Pin
Russell Robinson26-Jan-00 10:37
sussRussell Robinson26-Jan-00 10:37 
GeneralRe: Another idea which gets rid of the problem of having to write a new class Pin
Bulent Ozkir5-Oct-00 21:59
sussBulent Ozkir5-Oct-00 21:59 
GeneralUse STL Pin
Martin Holzherr25-Jan-00 2:11
sussMartin Holzherr25-Jan-00 2:11 
GeneralRe: Use STL Pin
Russell Robinson25-Jan-00 11:38
sussRussell Robinson25-Jan-00 11:38 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.150731.1 | Last Updated 25 Jan 2000
Article Copyright 2000 by Russell Robinson
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid