I have a function in my class which should get a multi-dimensional array. the problem is that the value of these dimensions is calculated in the class, using another function an
double calcSS(double tfpairexp[][max_ctrl_no][max_rep_no])
One solution is to change the function signature to,
double calcSS(double ***tfpairexp, int M, int N, int P);
where M
, N
and P
are dimensions of the arrray!
Or you can pass the instance of your class itself. After all, you've made the dimensions public in your class. And if this function is a member function of the class, then you don't even need to pass anything; you can access them from the function itself like this:
double calcSS(double ***tfpairexp)
{
for(int i = 0 ; i < cchips ; i++ )
{
for(int j = 0 ; j < max_ctrl_no ; j++ )
{
for(int k = 0 ; k < max_rep_no ; k++ )
{
//access elements as tfpairexp[i][j][k]
}
}
}
}
You can see this answer if it solves your problem: using a function template
The kind of arrays in you are using here (C-style) are not really designed to be used with dynamic sizes, though you can use new
to allocate them that way. One solution for function calling is do use a double ***
and three size_t
parameters for dimensions to pass into a function, but that still requires you to declare the array in the caller with dimensions as large as you will ever need. or you will corrupt your process memory and likely crash.
A better solution is to use vector
which is designed from the beginning to deal with array with runtime-determined sizes. You can either declare a multi-D vector and use it directly, or go for a single-dimensional vector and do a bit of math at access time to convert a triple of coordinates into an index into the vector.
Either way, you need the vector header, here is how I recommend placing that setup:
#include <vector> // in your includes
using std::vector; // at global scope immediately after all #includes
Some code samples. I'll use cchips
for the size of the third dimension based on another answer. The multidimensional solution looks something like this:
// at global scope
typedef vector< vector<double> > vec2double;
typedef vector< vector<vec2double> > vec3double;
// in the caller of your calcSS after you know how big to make the array {
vec3double tfairexp(cchips, vec2double(max_ctrl_no, vector<double>(max_rep_no)));
// now fill up tfairexp
calcSS(tfairexp);
// }
// important: pass a reference here, or you will copy the whole array at call time!
void calcSS(vec3double &tfairexp) {
// you can use cchips etc here but don't have to:
for (size_t i = 0; i < tfairexp.size(); i++) {
for (size_t j = 0; j < tfairexp[0].size(); j++) {
for (size_t k = 0; k < tfairexp[0][0].size(); k++) {
// access tfairexp[i][j][k] here
}
}
}
}
That solution will actually do 1+j+j*k
allocations of dynamic arrays. You could instead write a wrapper class that would "own" the vector and do the dimension-translation stuff, and have the class you're currently writing use that. I'm making some stylistic sacrifices to continue to use your "public class member variables for dimension sizes" approach. However, this one more closely models how the compiler translates C-style multidimensional arrays, and only does one memory allocation per run:
// as a member of your class -- returns a live reference that can be assigned to!
double &vec3_get(vector<double> &array, const size_t i, const size_t j, const size_t k) {
return array[i*max_ctrl_no*max_rep_no + j*max_rep_no +k];
}
// in caller of calcSS {
vector<double> tfairexp(cchips*max_ctrl_no*max_rep_no);
// fill in by doing vec3_get(tfairexp, i, j, k) = val;
calcSS(tfairexp)
// }
// again, pass a reference to the vector!
void calcSS(vector<double> &tfairexp) {
for (size_t i = 0; i < cchips; i++) {
for (size_t j = 0; j < max_ctrl_no; j++) {
for (size_t k = 0; k < max_rep_no; k++) {
// access vec3_get(tfairexp, i, j, k) here
}
}
}
}