Указатель на косвенное обращение с массивом

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

int ***s = new int **[row];
*s = new int *[row];
**s = new int[row];

Теперь, если бы я мог использовать только int, а не массивы,

***s = 1;

Чтобы сохранить его в желтом квадрате на моей картинке, но я не знаю, как получить доступ к элементам массива, я попробовал несколько вещей, и он либо вылетает, либо не компилируется. Любая помощь, даже указав мне в правильном направлении, была бы очень полезна. Спасибо.

диаграмма указателя

2 ответа

Решение

Вы создали что-то вроде этого (предположим, row 2 и тип T):

                           T ***
                          + ----- +
                          | |
                          + - / -+
                            /
                           / T**
                       +- / - + ----- +
                       | | |
                       + ----- + - + - +
                       - / |
                    -/      T* |
                +- / - + ----- + + - + --- + ----- +
                | | | | | |
                + ----- + ----- + + - + -+-----+
            ----/      -/        |      \---
      -----/        - /      T   |          \-
  + - / - + ----- + + - / - + ----- + + - + - + ----- + + -\- +-----+
  |     |     | |  X  |     | |     |     | |     |     |
  +-----+-----+ +-----+-----+ +-----+-----+ +-----+-----+

Каждый узел будет указывать на первый узел следующего уровня. Разыменование каждого уровня даст следующий уровень, но вы также должны позаботиться об индексе элемента в массиве, который вы хотите достичь. Это, я вижу, не сделано в вашем коде. Для скаляров вы разыменовываете используя * в то время как для массивов синтаксис индекса массива слишком разыменовывается, кроме выбора правильного элемента. * на массивах просто даст вам первый элемент всегда.

Чтобы получить доступ X на рисунке выше вы бы сделали

T** v = u[0];
T* w = v[1];
T x = w[0];
// shorthand for above
x = u[0][1][0];

Чтобы просто иметь массив на последнем уровне, вы должны делать это

int*** p = new int**;
*p = new int*;
**p = new int[row];

Это просто даст вам █ → █ → █ → █ █ █ …, где p Само по себе (первый блок) является автоматической переменной (обычно хранится в пространстве стека), а остальное приходит из свободного хранилища (обычно находящегося в куче).

Живой пример.

Скажем row = 3 для этого примера.

int ***s;
// s=[?]
// s is an uninitialized variable.

s = new int **[row];
// s[*] -> [?]
//         [?]
//         [?]
// s points to the first element of an array of size 3.
// The elements are uninitialized.

*s = new int *[row];
// s=[*] -> [*] -> [?]
//          [?]    [?]
//          [?]    [?]
// We've initialized s[0]. It points to another array of size 3.
// All elements of that array are also uninitialized, along with s[1] and s[2].

**s = new int[row];
// s=[*] -> [*] -> [*] -> [?]
//          [?]    [?]    [?]
//          [?]    [?]    [?]
// More of the same. s[0][0] is initialized.
// This last array contains uninitialized ints, not pointers.

***s = 1;
// s=[*] -> [*] -> [*] -> [1]
//          [?]    [?]    [?]
//          [?]    [?]    [?]
// We traverse three levels of pointers (->) and store 1 in the cell.

Все это должно скомпилироваться и работать нормально (если у вас нет доступа ни к одному из неинициализированных элементов).


s + 1 указывает на второй элемент первого массива.

// s=[*] -> [*] -> [*] -> [1]
// s + 1 -> [?]    [?]    [?]
//          [?]    [?]    [?]

*(s + 1) относится к клетке [?] указал на s + 1 на диаграмме выше. Эта ячейка неинициализирована.

**(s + 1) пытается разыменовать указатель мусора, который недопустим (и часто вылетает).

Другие вопросы по тегам