Почему мы используем двойные указатели для ссылки на двумерный массив, выделенный в куче?

0

Таким образом, в лекционном примере приведен следующий код

 int **a;
 a = new int*[10];
 for (int i = 0; i < 10; ++i){
      a[i] = new int[5];
      for (int j = 0; j < 5; ++j){
           a[i][j] = i*10+5;
      }
 }

И у меня есть несколько вопросов о вышеупомянутом коде (и многомерных массивах в куче вообще):

  1. Должны ли мы инициализировать каждый элемент массива, как показано? Или достаточно вырезать код после a [i] = new int [5]?
  2. Я знаю с массивами, выделенными в стеке, незаконно использовать переменную как размер стека как

    cin >> n;

    int a [n];

    но является ли он законным для массивов, распределенных по кучам? Как и в, a = new int [n]?

  3. Почему это двойной указатель, указывающий на этот массив? Обычно для 1D-массивов мы использовали один указатель как int * a = new int [10]? Если бы мне захотелось значение самого элемента массива, я бы почудился дважды как ** a? Или я все еще делаю * а?

  4. Так сказать, у меня есть 2D-массив объектов некоторого класса. Как я могу получить доступ к полю члена var i-го, j-го элемента? Что делать, если я хочу вызвать функцию-член объекта в i-м, j-м элементе?

  • 0
    Обратите внимание, что в «современном» C ++ (21-й век) мы бы этого больше не делали. Мы просто напишем std::vector<std::vector<int>> a(5, std::vector<int>(10)); чтобы получить 5x10 нулевой инициализированный 2D-массив. Ваша лекция устарела почти на 2 десятилетия.
Теги:
arrays
multidimensional-array
pointers

2 ответа

2
Лучший ответ
  1. Вам не нужно инициализировать каждый элемент массива. Если вы этого не сделаете, содержимое массива будет неопределенным. Кроме того, вы можете инициализировать нуль с помощью new int[5]().

  2. a = new int[n] работает в куче, потому что на самом деле существует вызов во время выполнения, чтобы отметить новую память для использования в качестве данных, a указывает a. Он не может работать в стеке, потому что компилятор должен знать, насколько большой фрейм стека для любого конкретного вызова функции, поэтому значение должно быть вычислимым во время компиляции.

  3. Вам нужен двойной указатель, потому что a является указателем на указатель на целое число. Он указывает на массив массивов, каждый из которых должен быть разыменован при доступе к значению. Обычно вы используете [i] [j] для доступа к определенному элементу, который эффективно удваивает отклонения.

  • 1
    **a дает вам первый элемент первого ряда. Обычно для доступа к элементу используется a[i][j] . Кроме того, упоминание new int[5]() для инициализации нулями было бы хорошо упомянуть в ответе.
  • 0
    @MooingDuck, я включил предложенные вами изменения.
Показать ещё 1 комментарий
1

Если количество столбцов в матрице известно во время компиляции, вы можете просто выделить матрицу:

int nrow = 10;                        // number of rows assigned at run time
int (*a)[5];                          // pointer to array of 5 ints
    a = new int[nrow][5];             // allocate matrix
    for (int i = 0; i < nrow; ++i)    // initialize matrix
        for (int j = 0; j < 5; ++j)
            a[i][j] = i*nrow+j;
    // ...
    delete[] a;

Ещё вопросы

Сообщество Overcoder
Наверх
Меню