выполнить миграцию кода с использованием динамически распределенных многомерных массивов C99 в переполнение стека

Я пытаюсь научиться делать что-то в C ++, и один из аспектов, с которыми я сталкиваюсь, — это как эффективно реализовать динамически распределенные многомерные массивы.

Например, скажем, у меня есть существующая функция:

void myfunc(int *lambda, int *D, int *tau, int r[*tau][*D])
{
int i, j, k, newj, leftovers;

r[0][0] = *lambda;
j = 0; // j indexes the columns; start with zero
for(i = 1; i < *tau; i++){ // i indexes the rows
leftovers = *lambda;
for(k = 0; k < j; k++){
r[i][k] = r[i - 1][k]; // copy prior to j
leftovers = leftovers - r[i][k];
}
r[i][j] = r[i - 1][j] - 1; // decrement
r[i][j+1] = leftovers - r[i][j]; // initialize to the right of j

if(j == *D - 2){ // second to last column
for(k = 0; k <= j; k++){ if(r[i][k] != 0){ newj = k; } }
j = newj; // can't think of a better way to do this
}else{
j++; // increment j
}
} // next row please

}

Из того, что я прочитал, похоже, что общая рекомендация — использовать для этой цели std :: vector. Кто-нибудь захочет предложить какой-нибудь совет или фрагмент кода о том, как реализовать вышеприведенную матрицу r, используя эквивалент std :: vector?

Я бы подумал, что это довольно распространенная ситуация, но, что интересно, Google обнаружил менее 50 хитов для «C99 в C ++».

Спасибо!
Бен

1

Решение

Я думаю, что это будет самое простое преобразование:

void myfunc(int *lambda, std::vector<std::vector<int> > &r)
{
int i, j, k, newj, leftovers;
int tau = r.size();

r[0][0] = *lambda;
j = 0; // j indexes the columns; start with zero
for(i = 1; i < tau; i++){ // i indexes the rows
int D = r[i].size();
leftovers = *lambda;
for(k = 0; k < j; k++){
r[i][k] = r[i - 1][k]; // copy prior to j
leftovers = leftovers - r[i][k];
}
r[i][j] = r[i - 1][j] - 1; // decrement
r[i][j+1] = leftovers - r[i][j]; // initialize to the right of j

if(j == D - 2){ // second to last column
for(k = 0; k <= j; k++){ if(r[i][k] != 0){ newj = k; } }
j = newj; // can't think of a better way to do this
}else{
j++; // increment j
}
} // next row please
}
2

Другие решения

У вас есть множество вариантов.


Быстрая смена:

void myfunc(const int& lambda, const size_t& D, const size_t& tau, int* const* const r) {
...

Используя vector (который не будет обеспечивать соответствие размеров при компиляции):

void myfunc(const int& lambda, std::vector<std::vector<int>>& r) {
const size_t tau(r.size()); // no need to pass
const size_t D(r.front().size()); // no need to pass
...

Или используя std::array для статических размеров:

enum { tau = 5, D = 5 };
void myfunc(const int& lambda, std::array<std::array<int,D>,tau>& r) {
...

Или используя параметры шаблона для фиксированных размеров:

template < size_t tau, size_t D >
void myfunc(const int& lambda, std::array<std::array<int,D>,tau>& r) {
...

или просто:

template < size_t tau, size_t D >
void myfunc(const int& lambda, int r[D][tau]) {
...

Обратите внимание, что вы также можете комбинировать статические и динамические массивы по мере необходимости в C ++.


Наконец, Multi Arrays здесь, чтобы помочь вам: http://www.boost.org/doc/libs/1_53_0/libs/multi_array/doc/user.html

0

Я бы изменил все r [x] [y] на R (x, y) и использовал бы

int * r;
#define R(x,y) r[ (x) * (*D) + (y) ]

Или, может быть, изменить * D на * Тау, я никогда не могу держать это прямо.

-1