I have a class that needs to store an array with a variable size. Ideally, this size would be defined as a parameter given to the constructor of the class.
I can define a constant and then work with that, as seen below:
#include <iostream>
#define ARRSIZE 5
class Classy{
private:
int myarray[ARRSIZE];
public:
Classy();
void printarray();
};
Classy::Classy(){
for(int i = 0; i < ARRSIZE; i++){
myarray[i] = i * i * 2;
}
}
void Classy::printarray(){
for(int i = 0; i < ARRSIZE; i++){
std::cout << myarray[i] << std::endl;
}
}
However, I'd like to do it like this:
#include <iostream>
class Classy{
private:
int arraysize;
int myarray[arraysize];
public:
Classy(int parraysize);
void printarray();
};
Classy::Classy(int parraysize){
arraysize = parraysize;
for(int i = 0; i < arraysize; i++){
myarray[i] = i * i * 2;
}
}
void Classy::printarray(){
for(int i = 0; i < arraysize; i++){
std::cout << myarray[i] << std::endl;
}
}
The compiler really doesn't like my approach though, so I am looking for an alternative way of doing things.
I did some googling on the subject, but my searches did not come up fruitful. I found this approach which does it using dynamic memory allocation. This is something I'd like to avoid, so I am looking for a solution that does not rely on that. It might well be (and I'm starting to think) that it is the only elegant solution to my problem (and if this is the case, the question should of course be closed as duplicate).
The C99 standard allows variable sized arrays (see this). But, unlike the normal arrays, variable sized arrays cannot be initialized.
You initialize an array variable by including an array literal in a New clause and specifying the initial values of the array. You can either specify the type or allow it to be inferred from the values in the array literal.
To use the array, we can initialize it with the new keyword, followed by the data type of our array, and rectangular brackets containing its size: int[] intArray = new int[10]; This allocates the memory for an array of size 10 . This size is immutable.
It is required to use dynamic allocation, because sizeof (Classy)
must be a compile-time constant. There's no way for your object's internal size to grow. But dynamic allocation doesn't have to be as complicated as that link suggests.
You can do it like this:
#include <memory>
class Classy
{
private:
int arraysize;
std::unique_ptr<int[]> myarray;
public:
Classy(int parraysize);
void printarray();
};
Classy::Classy(int parraysize)
: arraysize{parraysize}
, myarray{new int[arraysize]}
{
for(int i = 0; i < arraysize; i++){
myarray[i] = i * i * 2;
}
}
#include <iostream>
void Classy::printarray()
{
for(int i = 0; i < arraysize; i++){
std::cout << myarray[i] << std::endl;
}
}
This will allow the size to vary at the moment of creation, and be fixed thereafter. std::unique_ptr
will take care of automatically destroying the array contents when your object is dying.
You want to use templates to solve this problem:
#include <array>
template<std::size_t ArraySize>
class Classy final
{
public:
static const std::size_t size = ArraySize;
/* The rest of your public interface here */
private:
std::array<int, ArraySize> m_array;
};
Then you can use your class like this:
int main()
{
Classy<5> hasArrayOfFiveElements;
return 0;
}
You could very well opt to not use std::array, in preference for a c-style array. But we're writing C++, so let's use the better language facilities we have available to us :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With