Функции в C++ для начинающих Передача в функцию двумерного динамического массива

В С++ массивы в чистом виде должны быть представлены программе с заранее оговорённым числом ячеек, это число ячеек задаётся константным числом. Такие массивы иногда неудобно использовать: нельзя вводить количество ячеек в ходе работы программы. Пример обработки чистых массивов приводится в статье Функции в С++ для начинающих. Передача в функцию обычных массивов. Из-за этого во многих случаях вместо чистых массивов используют указательные переменные. Если переменная является указателем, то логично отдавать в функцию указатель.
В простейшем случае, когда используется одномерный массив, можно писать код вида:

В параметре функции foo заявлено, что в функцию придут указательная переменная и целое число. При обращении к функции foo такие данные ей и отдаются. Поскольку и типы, и количество уходящих в функцию данных соответствуют, функция срабатывает без проблем. По тому же принципу работает и передача в функцию указателей, указывающих на многомерные массивы (одномерные, двумерные, трёхмерные…). Основная трудность для начинающих, насколько я могу судить по себе, не в передаче в функцию указателей, а выдача и отбор памяти. Передать в функцию двумерный динамически-создаваемый массив достаточно просто:

Смысл простой: количество звёздочек указательной переменной зависит от мерности массива (одномерны — одна, двумерный — две и т. д.). Поскольку в функцию уходит указательная переменная, а параметр у функции такая же указательная переменная, то всё проходит гладко. Параметр легко принимает значение аргумента.
  • Хотя и говорят, что подобная работа — это работа с двумерным массивом, это не так. Выдача новичкам сведений о том, что работа с использованием указательных переменных — это работа с массивом, является только некоторым допущением, служащим для облегчения жизни начинающим программистам. Указатели есть указатели, а массивы есть массивы.
Для решения задач, требующих обработки массивов, не обязательно вникать в указатели. Указатели и массивы тесно взаимосвязаны, достаточно осознавать тот факт, что указатели и массивы не одно и то же, но при этом указатели можно использовать как массивы.
В ходе работы программы, созданной из листинга #1, количество ячеек задаётся с клавиатуры. После ввода количества ячеек (строк и колонок) программа берёт свободную память, столько памяти берёт, сколько мы ей сказали взять. Мы сказали ей взять памяти под row строк и col колонок. После этого происходит обращение к двум функциям: к функции заполнения массива, к функции вывода массива на экран, — а после происходит освобождение памяти. Освобождение памяти требуется только тогда, когда массив больше не будет использоваться. После того, как мы почистили память, указательную переменную, выполняющую роль массива, мы уже совсем не используем.
Поскольку списки параметров обеих функций одинаковые, я буду писать об обеих функциях как об одной. Вы можете смотреть на любую.
Благодаря тому, что первым в списке параметров заявлен параметр указательного характера (int **arr), влияние этого параметра распространяется и на ушедший в функцию аргумент (int **p), поэтому и заполнение, и вывод срабатывают. О влиянии заявленных для функции параметров на уходящие в функцию аргументы можно узнать из статьи Параметры функций в C++ для начинающих.
Чтобы работать с ячейками памяти, выделенными для массива, нужно знать их количество. Для чистого массива можно использовать операцию sizeof, с помощью которой несложно вывести число ячеек в массиве, но в случае передачи массивов в функции — названия массивов приводятся к указательным переменным, а применение операции sizeof к указательным переменным не позволяет выводить число ячеек, поэтому в функции уходят два вспомогательных параметра (поскольку массив предполагается двумерный, то два, для одномерного был бы один, для трёхмерного три), эти параметры нужны нам для работы над массивом.
На этом можно и закончить, но я приведу ещё два примера: пример с указателем на одномерный массив и пример с указателем на двумерный массив. Эти примеры могут помочь вам отследить логическую нить создания функций, в которых можно обрабатывать массивы использованием указательных переменных.
Пример на одномерном массиве:

Для двумерного массива используется тот же подход:

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

Вам нужно запомнить:

  • Указательные переменные часто используются как массивы, но массивами они не являются.
  • В случае передачи одномерного массива в функцию имя массива будет приведено к указателю, поэтому в параметрах функции для приёма одномерного массива часто используют параметр указательного характера.
  • Для работы с многомерными массивами можно использовать указательные переменные, которые будут выполнять роль многомерных массивов. Указательные переменные вполне пригодны для работы над массивоподобными сущностями.
  • При ручном выделении памяти нужно обязательно память и подчищать, при этом подчищать память нужно правильно.
  • Если уходящий в функцию аргумент является указательной переменной, то принимающий его параметр должен быть либо ссылкой (и лучше ссылкой, потому что так удобнее), либо указателем свыше (т. е. еслив функцию уходит аргумент с типом int**, то параметр должен быть int***). Использование параметра ссылочного типа избавит вас от нужности или ненужности разыменовывания указательной переменной в некоторых местах внутри функции.
  • При передаче в функцию массивов нужно отдавать в функцию и вспомогательные данные, т. е. нужно сообщать в функцию и массив, и количество его ячеек. Эти вспомогательные данные, окажущиеся внутри функции, нужны прежде всего вам.

14 комментариев на «“Функции в C++ для начинающих Передача в функцию двумерного динамического массива”»

  1. Alexsandr:

    Объясните пожалуйста следующую строку :
    int **A; //Для создания двумерного массива удобен указатель на указатель

    Во многих примерах встречаются «указатель на указатель», опишите подробнее их отличие от одного указателя и суть этой записи.

    • Конкретно в этом примере объясняю. А вообще суть использования от примера зависит. Было бы все с указателями просто, не советовали бы их избегать.

      Если делать одномерный массив из неизвестного заранее количества элементов, то в C++ НЕ получится НЕ использовать указатели. Возможно вы уже знакомы с созданием такого одномерного массива. Для создания одномерных массивов достаточно одного указателя.

      Двумерный массив можно описать как Одномерный массив, который содержит какое-то количество одномерных массивов одинаковой длины. Массив содержит массивы. Плюс к этому двумерный массив можно представить в виде таблицы на плоскости. Самая обычная таблица всегда состоит из строк и колонок.

      Первый используемый указатель используется чтобы выделить память под начало каждой строки, второй указатель — это массив, который содержится в этой строке.
      Точнее говоря первый массив — только указатели на начало строк.
      =============================
      примечание. Колонка или строка это будет — принципиального значения не имеет. Также чтобы не мешать все в кашу, там и выделение, и чтение элементов и модификация элементов.

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

  2. Alexsandr:

    Спасибо, этой информации более чем достаточно.

  3. Akjol:

    А как в функцию ввести двухмерный не динамический массив, а обычный обьявленный как а100 на 100 ?

    • Так можно

  4. Vera:

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

    • Наверное никак. Вот я спрашивал, но ответа не получил тогда
      http://www.cyberforum.ru/cpp-beginners/thread731832-page2.html
      _____________________________________________
      Когда объявлется динамчески создаваемый массив, то неизвестны адреса памяти, в которых элементы такого массива будут расположены, а вот как положить что-то в неизвестно куда?
      Элементы динамического массива располагается в некоторого рода хаотичном порядке. Поэтому сначала он просто создается, а потом в него уже присваиваются элементы. Любые хитровыводимые приемы не более чем создание просто вида инициализации.

  5. Спасибо большое за такое подробное объяснение. Сам я учусь пока что на С программировать, но тут все так понятно, что я смог сделать тоже самое и при этом все понял 🙂 Долго не мог понять, как вывести динамический массив через функцию, то параметры не так указывал, то массив в самой функции вводил. Все решил, спасибо автор!

  6. Аноним:

    Что за клоун выбирал такую расцветку для кода?

  7. Аноним:

    Расцветка — супер

  8. Аноним:

    Зачем передавать при удалении количество ел-ов если вы в этом примере не использовали это?

  9. Аноним:

    Написать собственную функцию с аргументами не возвращающую значение, которая выводит название дня недели, в зависимости какое число было введено пользователем.
    С помощью функции не шарю.Может есть кто хочет помочь.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Поиск

 
     

Случайная книга в электронном формате

https://www.litres.ru/tatyana-pavlovskaya/c-c-strukturnoe-i-obektno-orientirovannoe-programmirovanie-praktikum-586035/?lfrom=15589587
Яндекс.Метрика