2

I am trying to initialize an array of size n based off the input argument of my constructor. This works:

//Inside Header
class runningAverage{
    private:
        byte n;
        float array[10];
    public:
        runningAverage(byte);
};

//Inside .cpp
runningAverage::runningAverage(byte a){
    n = a;
    for (byte i = 0; i<n; i++) {
        array[i] = 0;
    }
}

and this does not work:

//Inside Header
class runningAverage{
    private:
        byte n;
        float array[];
    public:
        runningAverage(byte);
};

//Inside .cpp
runningAverage::runningAverage(byte a){
    n = a;
    for (byte i = 0; i<n; i++) {
        array[i] = 0;
    }
}

I want to initialize the array so that is the size specified by n. This way I don't waste memory by arbitrarily specifying float array[256] or something like that. Any help is appreciated!

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
ewoolsey
  • 91
  • 1
  • 7

3 Answers3

6

You have to actually allocate the array; and you'll want to use a pointer type, float array[] is not what you think there. As juanchopanza reminds us, you'll also want to either disable the copy constructor and assignment operator, or implement ones that do a proper deep copy.

//Inside Header
class runningAverage{
    private:
        byte n;
        float *array; // <= correct type
    public:
        runningAverage(byte);
        ~runningAverage(); // <= you'll need a destructor to cleanup
    private:
        runningAverage(const runningAverage &);
        runningAverage & operator = (const runningAverage &);
};

//Inside .cpp
runningAverage::runningAverage(byte a){
    array = new float[n]; // <= allocate array
    n = a;
    for (byte i = 0; i<n; i++) {
        array[i] = 0;
    }
}

// clean up
runningAverage::~runningAverage(){
    delete[] array;
}

However, if you have some dynamic, automatic container at your disposal (e.g. std::vector) you might want to use that instead - then you don't have to deal with copy / assignment / destructor / memory management.

Jason C
  • 38,729
  • 14
  • 126
  • 182
  • 2
    Better to also provide copy and assignment operators, or disable those operations. – juanchopanza Aug 06 '14 at 06:11
  • 1
    Wow thanks this solved my problem. Just a couple questions. Do you really need a destructor if it will never be called? And let me get this straight, array is declared as a pointer to a float. then at new float[n], you are allocating memory for the array? also why do you have the square brackets after delete? – ewoolsey Aug 06 '14 at 06:19
  • What are copy and assignment operators? @juanchopanza – ewoolsey Aug 06 '14 at 06:20
  • 2
    BTW you don't need the loop in the constructor, you can zero-initialize the array elements like this: `array = new float[n]();`. – juanchopanza Aug 06 '14 at 06:22
  • @user3912409 ["c++ copy constructor and assignment operator"](https://www.google.com/search?q=c%2B%2B+copy+constructor+and+assignment+operator). You should get into the habit of always defining a destructor when special cleanup is needed, for a dozen+ very good reasons. – Jason C Aug 06 '14 at 06:28
  • @user3912409 Your analysis of `new float[n]` is correct. `delete[]` is array delete and must be used when array new is used. See for example http://stackoverflow.com/questions/1553382/is-delete-equal-to-delete and others. – Jason C Aug 06 '14 at 06:33
3

If you only know the size at runtime, Jason C's answer is what you want. ( With juanchopanzas comment )

If the size is known at compile time, you can use templates:

template < int SIZE >
class runningAverage
{
    float array [ SIZE ];
};

runningAverage < 10 > ra;

Or use classes like std::array instead of std::vector.

Slyps
  • 607
  • 4
  • 9
  • Is there an advantage to using this method over Jason's? I don't have any experience with templates.... – ewoolsey Aug 06 '14 at 06:29
  • @user3912409 There are advantages and disadvantages and the topic is discussed in many other places and a bit much to go into here. – Jason C Aug 06 '14 at 06:30
  • In some situations jasons answer is more fit, in some situations mine. The only advantage independend of what your needs are, is that my method doesn't require you to deal with copy/assignment operators. However that problem is also solved for you if you just use `std::vector`. All the other (dis)advantages of each method depends on what you are actually using this code for, so I can't answer that right here. – Slyps Aug 06 '14 at 06:34
  • Oh yea and I forgot: A disadvantage of my code is like I said in my answer, you need to know the size at compile time. – Slyps Aug 06 '14 at 06:38
1
  1. Your member should be a pointer so that dynamic memory allocation can happen when object is constructed: float *array;.
  2. In constructor, use array = new float[a];
  3. In constructor, initialize preferably using memset rather than a loop.
  4. Have a destructor to release the memory with this line: delete[] array;
  5. To get it to compile, you need this line: #include <new>
  6. To link, don't forget to include linker flag -lstdc++ when using g++.

Since you appear to be a beginner, take a look at this useful reference for you study: http://www.cplusplus.com/doc/tutorial/dynamic/

coder.in.me
  • 1,048
  • 9
  • 19