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

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

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

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

***s = 1;

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

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

1

Решение

Вы создали что-то вроде этого (предположим, 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 Само по себе (первое поле) является автоматической переменной (обычно хранится в пространстве стека), а остальное приходит из свободного хранилища (обычно находящегося в куче).

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

2

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

Скажем 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) пытается разыменовать указатель мусора, который является недопустимым (и часто вылетает).

1

По вопросам рекламы [email protected]