Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variable Length Arrays: How to create a buffer with variable size in C++

I am currently writing a moving average class.

The goal is to be able to specify the buffer size as part of the constructor when a new object of class Running_Average is created.

#include <iostream>
#include "Complex.h"
#include <cmath>
#include<stdio.h>
#include<stdlib.h>
#include <windows.h>

using namespace std;

class Running_Average
{
public:
    double sum = 0;
    double average = 0;
    int i;

    double Average(void); // Member functions declaration
    void AddSample(double);
    Running_Average(int);
};


Running_Average::Running_Average(int size) {
    int buffersize = size;
    double buffer[buffersize] = { 0 };
}

void Running_Average::AddSample(double val)  //Add new values to buffer
{
    for (i = 9; i>0; i--)
    {
        buffer[i] = buffer[i-1];
    }
    buffer[0] = val;
}

double Running_Average::Average(void) //Calculate Average of current values in buffer
{
    for (i = 0; i<buffersize; i++)
    {
        cout << buffer[i] << endl;
        sum += buffer[i];
    }
    average = sum / buffersize;
    sum = 0; 
    return average;
}

int main()
{
    double value;
    int i;
    int f = 0;
    Running_Average test;

    for (i = (40); i < (50); i++)
    {
        test.AddSample(i);
    }

    while (1) 
    {
        i = rand() % 100;
        test.AddSample(i);
        value = test.Average();
        cout << endl;
        cout << value << endl;
        cout << endl; 
        Sleep(1000);
    }

}

However, the constructor is giving me grief:

Running_Average::Running_Average(int size) {
    int buffersize = size;
    double buffer[buffersize] = { 0 };
}

Specifically:

buffer[buffersize]

throws an error in visual studio saying:

expression must have a constant size.

I want the user to specify what buffer size they want to work with when they create a new object by passing their value to the constructor.

How can I make this work without it throwing an error?

Thanks for your help!

EDIT: SOLVED! Thank you everyone for your assistance! I managed to get the function working by using the std::vector to define a variable sized array.

like image 790
Andrew Schroeder Avatar asked May 29 '18 03:05

Andrew Schroeder


2 Answers

There are plenty of ways to do this. The ones that come to mind from best to worst are :

1 Use std::vector

int buffersize = size;
std::vector<double> buffer(buffersize);

2 Built-in unique pointer or shared pointer (depending on usage)

int buffersize = size;
auto buffer = make_unique<double[]>(buffersize) // C++14

int buffersize = size;
auto buffer = make_shared<double[]>(buffersize) // C++14

3 Allocate manually

int buffersize = size;
double *buffer = new double[buffersize];

// delete [] buffer, must be called later

4 Allocate on the stack (not advised, and platform dependent)

int buffersize = size;
double *buffer = alloca(buffersize * sizeof(*buffer));

Note that in all these cases you could index buffer just like an array.

like image 142
Kostas Avatar answered Oct 06 '22 01:10

Kostas


Standard C++ doesn't have variable length arrays. (Why?) The size of an array must be a constant expression. Some compilers have non-standard extensions that allow VLAs, but you shouldn't rely on them. Use std::vector when you need an array which can have a variable length and can be resized.

like image 26
eesiraed Avatar answered Oct 06 '22 01:10

eesiraed