4 / 4 / 0
Регистрация: 26.10.2014
Сообщений: 105
|
|||||||||||
1 | |||||||||||
Многомерные массивы08.10.2015, 17:12. Показов 1242. Ответов 8
Метки нет Все метки)
(
Здравствуйте, уважаемые форумчане!
Давненько я не задавал здесь своих глупых вопросов по плюсам. Надо бы исправить ситуацию: В общем, я всегда думал, что хорошо понимаю указатели, но, встретив во многих кодах двойные и даже тройные указатели, решил поэкспериментировать и понял, что не так уж хорошо и понимаю тему. Вот, например:
1) Не понимаю, почему не компилируется строка 13. В этой строке мы сначала обращаемся к содержимому нулевой ячейки голубого(на схеме) массива - это тройной указатель, который должен содержать адрес указателя на указатель на тип int. Я и передаю ему адрес такого указателя, которым является arr. По-моему, всё логично, но GCC со мной не согласен: error: cannot convert ‘int* (*)[3]’ to ‘int***’ in assignment ptr[0] = &arr; При этом такой код компилятором хавается:
В строке 19 освобождаем память, выделенную под красный массив - компилируется. В строке 21 освобождаем память, выделенную под чёрный массив - компилируется, но падает при выполнении: В строке 23 освобождаем память, выделенную под зелёный массив - компилируется. В строке 25 освобождаем память от голубого массива - GCC пишет: warning: deleting array ‘ptr’ delete [] ptr; ^ Я понимаю, что пытаюсь удалить массив, а почему бы нет? Ведь указатели, содержащиеся в этом массиве хранятся в каких-то ячейках памяти, которые я и хочу освободить от этих самых указателей. Почему нельзя? В общем, вопроса два: 1) Почему не компилируется строка 13? 2) Как правильно освободить память от всех этих массивов?
0
|
|
08.10.2015, 17:12 | |
Ответы с готовыми решениями:
8
Многомерные массивы, как перебирать внутренние массивы Многомерные массивы Многомерные и одномерные массивы Многомерные массивы и STL |
4 / 4 / 0
Регистрация: 26.10.2014
Сообщений: 105
|
||||||
08.10.2015, 18:19 [ТС] | 3 | |||||
Да, конечно, имелось-в-виду:
0
|
4 / 4 / 0
Регистрация: 26.10.2014
Сообщений: 105
|
|||||||||||
08.10.2015, 22:06 [ТС] | 4 | ||||||||||
Пожалуй, слишком много фигни я нагородил в этом посте. Попробую адекватно сформулировать вопросы. Итак, абстрагируемся от всего вышесказанного и рассмотри пару простеньких кодов:
В строках 3-6 объявляем указатель на массив(голубой) из трёх указателей на массивы(красные) типа int, в строках 7-9 освобождаем область памяти, выделенную под красные массивы, а в строке 10 освобождаем память, выделенную под голубой массив. Указатель arr будет удалён при выходе из области видимости. Всё понятно. А как насчёт такого кода:
Здесь конструкция аналогичная. В строках 7-9 освобождаем память, выделенную под красные массивы, но голубой-то массив указателей по-прежнему существует, надо бы нам освободить память, выделенную под него. Это я и пытаюсь сделать в строке 10, на что GCC меня успешно посылает: warning: deleting array ‘ptr’ delete [] ptr; ^ Почему во втором случае строка 10 не компилируется и как в этом случае освободить память от голубого массива указателей?
0
|
4 / 4 / 0
Регистрация: 26.10.2014
Сообщений: 105
|
||||||
08.10.2015, 23:38 [ТС] | 5 | |||||
Вот ведь я баран!
Дошло, наконец! Голубой массив-то в этом случае хранится не в куче, а в стеке - ясен пень, вызов оператора delete для него невозможен! Пойду убьюсь об стену... ![]() Добавлено через 59 минут Не хотелось бы показаться совсем шизанутым, но остался последний вопрос:
error: cannot convert ‘int* (*)[5]’ to ‘int***’ in assignment ptr = &arr; ^ Почему? Ведь, как в строке 7, так и в строке 8, arr является указателем на другой указатель, который, в свою очередь, указывает на тип int. Правда, указатель arr в строке 7 указывает не просто на указатель, а на массив указателей(нулевую ячейку этого массива), но ведь для компилятора разницы быть не должно. Так почему не компилируется?
0
|
18340 / 9525 / 2327
Регистрация: 30.01.2014
Сообщений: 16,646
|
|||||||||||||||||||||
08.10.2015, 23:58 | 6 | ||||||||||||||||||||
![]() Решение
Здесь пока что нужно не торопиться и внимательно поизучать тему массивов.
Главное, что нужно уяснить: массив - это не указатель! Массив только приводится к указателю неявно, но у массива свой тип. Вот тут:
К тому же, у тебя все равно второй массив имеет больше косвенностей, чем нужно. Можно было бы присвоить адрес первого элемента (который по значению совпадает с адресом массива) вот таким кодом:
Разбирайся. ![]() Добавлено через 11 минут Должно. И разница есть. Типизация у С++ статическая. Типы содержат метаинформацию (например размер). Так вот, указатель на массив содержит информацию о размерности массива (компилятор тебе об этом пишет явно). Эту информацию компилятор может использовать, например, для предоставления адресной арифметики на таком указателе. +1 - сместит значения адреса на размер целого массива (sizeof(int*) * 3). Поэтому нет сомнений, что указатель на массив из трех указателей и указатель на массив из четырех указателей будут вести себя по-разному при использовании адресной арифметики, а неявное преобразование такого указателя в обычный - приведет к потере информации о размере. Следовательно нет веских причин разрешать такое преобразование, как нет причин разрешать неявное преобразование int * -> double *. Приведение же имени массива в указатель на первый элемент - это особый, исключительный случай, который полностью перешел из С. Поэтому тут существует некая поблажка. Однако все остальные случаи попадают под правила более строгой, чем в С типизации, которая не разрешает просто так приводить типы. Например в С разрешается приводить несовместимые по типам указатели неявно почти в любых случаях, но в С++ - это запрещено. Поэтому за исключением некоторых принципиальных вопросов совместимости с С, С++ всегда будет контролировать типизацию, защищая тем самым от потенциальных ошибок.
1
|
4 / 4 / 0
Регистрация: 26.10.2014
Сообщений: 105
|
|
09.10.2015, 00:14 [ТС] | 7 |
DrOffset, Большое спасибо! Этого я не знал.
Добавлено через 9 минут А не подскажете, по какой причине вторая звёздочка в этом сообщении заключена в круглые скобки? По-идее, круглые скобки должны задавать приоритет выполнения этой звёздочки над, к примеру, оператором '[]'. В чём смысл скобок именно в этом случае?
0
|
18340 / 9525 / 2327
Регистрация: 30.01.2014
Сообщений: 16,646
|
|
09.10.2015, 00:36 | 8 |
Тут простая вещь зарыта на самом деле. Для многих это не понятно, потому что они сразу начинают ассоциировать то, что пишешь в коде, с ассемблером, а адресами, регистрами и т.п. Естественно у человека возникает недоумение, как это так, адрес-то одинаковый, чего же он не кастится!
Рассматривать так код тоже правильно и полезно, но этого мало. С++ высокоуровневый язык, у которого есть своя система типов. Система типов определяет правила игры при компиляции. И код компилятор строит опираясь на нее. Поэтому при анализе программы, прежде чем спуститься на низкий уровень, также полезно понимать что происходит во время компиляции, как типы в программе взаимодействуют в рамках правил языка. Добавлено через 8 минут Именно приоритет они и задают. Только в данном случае речь пойдет о приоритете разбора. См. например, вот эту статью: http://habrahabr.ru/post/100104/ Там как раз описан тот порядок, который используется при анализе таких выражений. (*) - указатель, переходим направо [3] - на массив из трех, переходим налево int * - указателей на int. Скобки указывают приоритет. Иначе вторая звездочка начнет относиться к левой части и мы получим совсем другое выражение: [3] - массив их трех, переходим налево int ** - указателей на указатель на int. Добавлено через 6 минут Вот еще полезная ссылка: https://msdn.microsoft.com/ru-... 2y1z4.aspx Плюс можешь поискать мои ответы на форуме на аналогичные темы.
1
|
4 / 4 / 0
Регистрация: 26.10.2014
Сообщений: 105
|
|
09.10.2015, 00:40 [ТС] | 9 |
Спасибо, буду изучать...
0
|
09.10.2015, 00:40 | |
Помогаю со студенческими работами здесь
9
Многомерные массивы (матрицы) Многомерные массивы. Тени Многомерные массивы. Матрица. Задача на Многомерные Массивы Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |