Передающий указатель на 2D C++ массива

У меня есть эта проблема в течение довольно долгого времени - я зафиксировал измеренный 2D массив как участник класса.

class myClass
{ 
public:
        void getpointeM(...??????...);
        double * retpointM();

private:

   double M[3][3];

};

int main()
{
     myClass moo;
     double *A[3][3];

     moo.getpointM( A );  ???
     A = moo.retpointM(); ???

} 

Я хотел бы передать указатель на M матрица снаружи. Это, вероятно, очень просто, но я просто не могу найти надлежащую комбинацию & и * и т.д.

Спасибо за справку.

6
задан Moomin 22 February 2010 в 04:39
поделиться

7 ответов

double * A [3] [3]; - это двумерный массив double * s. Вам нужен двойной (* A) [3] [3]; .

Затем обратите внимание, что A и * A и ** A имеют одинаковый адрес, только разные типы.

Создание typedef может упростить ситуацию:

typedef double d3x3[3][3];

Это C ++, вы должны передавать переменную по ссылке, а не по указателю:

void getpointeM( d3x3 &matrix );

Теперь вам не нужно использовать скобки в именах типов, и компилятор позаботится о том, чтобы вы передаем массив правильного размера.

9
ответ дан 9 December 2019 в 20:42
поделиться

Ваше намерение неясно. Что должен делать getpointeM? Вернуть указатель на внутреннюю матрицу (через параметр) или вернуть копию матрицы?

Чтобы вернуть указатель, вы можете сделать следующее

// Pointer-based version
...
void getpointeM(double (**p)[3][3]) { *p = &M; }
...
int main() {
  double (*A)[3][3];
  moo.getpointM(&A);
}

// Reference-based version
...
void getpointeM(double (*&p)[3][3]) { p = &M; }
...
int main() {
  double (*A)[3][3];
  moo.getpointM(A);
}

Для retpointM объявление будет выглядеть следующим образом

...
double (*retpointM())[3][3] { return &M; }
...
int main() {
  double (*A)[3][3];
  A = moo.retpointM();
}

Однако это довольно трудно читать. Вы можете сделать его намного понятнее, если будете использовать typedef-имя для типа массива

typedef double M3x3[3][3];

В этом случае приведенные выше примеры превратятся в

// Pointer-based version
...
void getpointeM(M3x3 **p) { *p = &M; }
...
int main() {
  M3x3 *A;
  moo.getpointM(&A);
}

// Reference-based version
...
void getpointeM(M3x3 *&p) { p = &M; }
...
int main() {
  double (*A)[3][3];
  moo.getpointM(A);
}

// retpointM
...
M3x3 *retpointM() { return &M; }
...
int main() {
  M3x3 *A;
  A = moo.retpointM();
}
3
ответ дан 9 December 2019 в 20:42
поделиться

Короткий ответ заключается в том, что вы можете получить double * в начало массива:

public:
   double * getMatrix() { return &M[0][0]; }

За пределами класса, однако, вы не можете тривиально превратить double * в другой двумерный массив напрямую, по крайней мере, не по той схеме, которую я видел.

Однако вы можете создать двумерный массив в main (double A[3][3]) и передать его в метод getPoint, который может скопировать значения в переданный массив. Это даст вам копию, что может быть тем, что вам нужно (вместо оригинальных, изменяемых данных). Недостатком является то, что вам придется копировать его, конечно.

0
ответ дан 9 December 2019 в 20:42
поделиться

Да, это сработает. API очень понятен («Имя хоста может быть либо именем компьютера, например» java.sun.com «, либо текстовым представлением его IP-адреса»), и, конечно, вы можете легко проверить себя.

-121--1573935-

То, что у вас есть, точно назад. O (lg N) обычно означает какой-то алгоритм деления и завоевания, и одним из общих способов реализации деления и завоевания является двоичное дерево. В то время как двоичные деревья являются существенным подмножеством всех алгоритмов разделения и завоевания, все равно являются подмножеством.

В некоторых случаях можно преобразовать другие алгоритмы разделения и завоевания достаточно непосредственно в двоичные деревья (например, комментарии к другому ответу уже сделали попытку утверждать, что двоичный поиск аналогичен). Однако для другого очевидного примера многоходовое дерево (например, В-дерево, В + дерево или В * дерево), в то время как очевидно, что дерево так же ясно , а не двоичное дерево.

Опять же, если вы хотите достаточно сильно, вы можете растянуть точку, что многоходовое дерево может быть представлено как своего рода деформированная версия двоичного дерева. Если вы хотите, вы, вероятно, можете растянуть все исключения из точки сказать, что все они (по крайней мере, что-то вроде) двоичных деревьев. По крайней мере, для меня все это делает «двоичное дерево» синонимом «разделяй и побеждай.» Другими словами, все, чего вы добиваетесь, это искажение словаря и, по существу, уничтожение термина, который является как отдельным, так и полезным.

-121--4144510-

Возможно, вы захотите взять код в своей основной функции, которая работает с 2D массивом двойников, и переместить его в myClass в качестве члена. Вам не только не придется сталкиваться со сложностью передачи указателя для этого массива 2D, но и с кодом, внешним для вашего класса, больше не нужно будет знать подробности того, как ваш класс реализует A, поскольку теперь они будут вызывать функцию в myClass и позволять этому выполнять работу. Если, скажем, позже вы решили разрешить переменные размеры A и решили заменить массив на вектор из вектора s, вам не потребуется переписывать какой-либо вызывающий код, чтобы он работал.

0
ответ дан 9 December 2019 в 20:42
поделиться
class myClass
{ 
public:
        void getpointeM(double *A[3][3])
        {
           //Initialize array here
        }

private:

   double M[3][3];

};

int main()
{
     myClass moo;
     double *A[3][3];

     moo.getpointM( A );
} 
0
ответ дан 9 December 2019 в 20:42
поделиться

В вашей функции main () :

double *A[3][3];

создает массив 3x3 из double * (или указателей на удвоения). Другими словами, 9 x 32-битных смежных слов памяти для хранения 9 указателей памяти.

Нет необходимости делать копию этого массива в main () , если только класс не будет уничтожен, и вы по-прежнему хотите получить доступ к этой информации. Вместо этого вы можете просто вернуть указатель на начало этого массива элементов.

Если вы хотите вернуть указатель только на внутренний член класса, вам действительно нужно только одно значение указателя в main () :

double *A;

Но если вы передаете этот указатель в функция и вам нужна функция для обновления ее значения, вам нужен двойной указатель (который позволит функции возвращать реальное значение указателя обратно вызывающей стороне:

double **A;

И внутри getpointM () вы можете просто указать A на внутренний элемент ( M ):

getpointeM(double** A)
{
    // Updated types to make the assignment compatible
    // This code will make the return argument (A) point to the
    // memory location (&) of the start of the 2-dimensional array
    // (M[0][0]).
    *A = &(M[0][0]);
}
0
ответ дан 9 December 2019 в 20:42
поделиться

Сделайте M публичным вместо приватного. Поскольку вы хотите разрешить доступ к M через указатель, M все равно не инкапсулируется.

struct myClass { 
  myClass() {
    std::fill_n(&M[0][0], sizeof M / sizeof M[0][0], 0.0);
  }
  double M[3][3];
};

int main() {
  myClass moo;
  double (*A)[3] = moo.M;
  double (&R)[3][3] = moo.M;

  for (int r = 0; r != 3; ++r) {
    for (int c = 0; c != 3; ++c) {
      cout << A[r][c] << R[r][c] << ' ';
      // notice A[r][c] and R[r][c] are the exact same object
      // I'm using both to show you can use A and R identically
    }
  }

  return 0;
}

В целом, я бы предпочел R, а не A, потому что все длины фиксированы (A потенциально может указывать на double[10][3], если бы это было требованием), и ссылка обычно приводит к более четкому коду.

0
ответ дан 9 December 2019 в 20:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: