Defining an Array in a Class

Hi,

I have a question regarding defining an Array within a class. I would like to define the Array size by one of the Class' variables.

For example:

One Class will work with 2 Output Pins, a second will work with 3 Pins. How can I define the size of the Array based on if it needs to be able to hold 2 or 3 variables?

const byte MaxClstrSize = 3;                              // Define Maximum Array Size for Array in Class below


class Glow_Class {                                        // defining a Class
   
public:                                                   // Class Member Variables. Initialized at startup
                                 
  byte ClstrPinsArr[MaxClstrSize];                        // Define an Array with the amount of 3 Max Members. If it only holds 2 pins, I'm wasting memory.
                                                          // How can I define this Array based on clstrSize?
  
  float ClstrSpeed;
  byte Pins;
  
  
  public:                                                 // Constructor - Creates a Glow_Class and initializes the member variables and state
  
    Glow_Class( float cSpeed,      byte clstrSize,    byte pins[]){             
      
      for (byte i = 0; i < (clstrSize); i++)
      {                                                    
          ClstrPinsArr[i] = pins[i];                         // load pins into Array. For clstSize 2, it leaves i=2 unchanged.                    
      }
  
      ClstrSpeed = cSpeed;
  
    }
  
    void Update() {
      
      // Do something... 
    }
};



//Cluster Size
byte Clstr_Size_1 = 2;
byte Clstr_Size_2 = 3;

// Define Pins
byte Clstr_Pin_1[2] = {1, 2};                                            // Array has 2 members  --> Clstr_Size_1 will be 2                 
byte Clstr_Pin_2[3] = {3, 4, 5};                                         // Array has 3 members  --> Clstr_Size_2 will be 3                  


Glow_Class Grp_1  ( 1, Clstr_Size_1,   Clstr_Pin_1);                     // Define Grp_1
Glow_Class Grp_2  ( 1, Clstr_Size_2,   Clstr_Pin_2);                     // Define Grp_2



void setup() {

}


void loop() {

  Grp_1.Update();                                                        // Update Classes
  Grp_2.Update();
}

Currently I'm "cheating" by defining the Array with the maximum amount of variables it might need to hold (in this case 3). If it will need it or not. But this seems like a waste of memory. (Especially if some Grps might write to 10 pins, others only to 2... In a case like this I wouldn't want to define all the Arrays with a size of 10 members)

In the above example, is it somehow possible to define the Array based on the variable clstrSize?
I'm sending a different clstrSize with Grp_1 and Grp_2? (clstrSize for Grp_1 = 2, clstrSize for Grp_2 = 3)

I hope I'm making sense here. I'm happy to try and explain better if it's not clear :slight_smile:

Thanks for your help and time.

You could use templates and pass the number of bytes to the template (ArduinoJSON does that)
You could use subclasses based on the number of bytes (not satisfying conceptually)
You could dynamically instantiate the memory (not recommended if lots of Allocation / Deallocation)
You could indeed swallow the cost and allocate more bytes than needed.
You could leave it up the the caller to create the array and pass a pointer to the array (and its size) only to the class

I would probably go for the last solution esp. if you have statically instanciated objects defined at compile time. That’s the approach taken by the Keypad class for example where 3 arrays are defined within the main code

 const byte rows = 4; //four rows
const byte cols = 3; //three columns
char keys[rows][cols] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'#','0','*'}
};
byte rowPins[rows] = {5, 4, 3, 2}; //connect to the row pinouts of the keypad
byte colPins[cols] = {8, 7, 6}; //connect to the column pinouts of the keypad

and then you instanciate the class and pass the two sizes and arrays’pointers Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, rows, cols );

Dynamically allocate it after you know the size?

Don't fear the pointers!

-jim lee

Thanks all.

To be honest, I don't know any of these things. But this will give me stuff to google and dig into and learn new things. Thanks all.

Jim Lee, That's what I am hoping to do, dynamically allocate it after I know the size. But how do I do that?
I have to declare the Array in the first public part (without knowing its size yet), so that I can use it later on. Is there another way or other place to define it?

Thanks again.

You can do something like this

In your class definition, declare a pointer

byte * ClstrPinsArr;

In your constructor, assign this pointer to the return value of malloc and check if it's valid

ClstrPinsArr = (byte *) malloc(clstrSize);

if (ClstrPinsArr == nullptr)
{
    // error, could not allocate memory
}
else
{
    // success, you can use ClstrPinsArr as an array
}

And don't forget to free this memory in the destructor, if necessary

if (ClstrPinsArr != nullptr)
{
    free(ClstrPinsArr);
}

Thanks guix, I will wrap my head around this and give it a try.

All the help is much appreciated.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.