У студента задача реализовать в коде алгоритм примерно такого вида (задание было несколько сложнее, я упрощаю):
// создать указатель на одномерный массив целых чисел
// вызвать функцию, которая создаст динамический массив, заполнит его данными
// и вернет его адрес в вызывающую функцию; полученный адрес нужно сохранить
// в созданный выше указатель на массив
// вывести элементы созданного массива в консоль
// освободить память, занятую массивом, когда он станет не нужен
Упомянутую функцию тоже нужно предварительно написать.
Я объяснил, что это можно написать разными способами, и предложил попробовать два варианта: возврат динамического массива из функции обычным способом (с помощью команды return) или через параметр-указатель.
1. Возврат динамического массива из функции с помощью return
Этим способом задачу решили довольно быстро, особых проблем не возникло. В интернетах по этой теме полно примеров (
например). Получилось что-то вроде следующего.
#include
int* createDynArray(int &size)
{
std::cout << "Введите размер массива: ";
std::cin >> size; // получить размер массива
int *arr = new int[size]; // выделить память под массив
for (int i{}; i < size; i++) arr[i] = i; // заполнить массив данными
return arr; // возвратить массив
}
int main()
{
// создать указатель на одномерный массив целых чисел
int *arr{ nullptr }; // указатель на первый элемент массива
int size{}; // размер массива
// вызвать функцию, которая создаст динамический массив, заполнит его данными
// и вернет его адрес в вызывающую функцию; полученный адрес нужно сохранить
// в созданный выше указатель на массив
arr = createDynArray(size);
// вывести элементы созданного массива в консоль
std::cout << "Полученный массив: ";
for (int i{}; i < size; i++)
std::cout << arr[i] << ' ';
std::cout << '\n';
// освободить память, занятую массивом, когда он станет не нужен
delete[] arr;
return 0;
}
Переменную size передаем в функцию по ссылке (это отмечено знаком амперсанда & в заголовке функции). Мы передаем в функцию пустую переменную, а функция в нее поместит размер созданного динамического массива, чтобы можно было найти окончание массива, когда мы будем перебирать его элементы для различных операций с массивом в программе. В вышеприведенной программе, например, мы используем заполненную функцией переменную size при выводе элементов массива в консоль.
Пример работы вышеприведенной программы в консоли:
Введите размер массива: 9
Полученный массив: 0 1 2 3 4 5 6 7 8
2. Возврат динамического массива из функции через параметр-указатель
Во втором случае что-то надолго задумались, а я не помнил точно, в чем там соль. Отложил себе на дом. На занятии написали следующее (привожу только фрагменты кода, отличающиеся от программы из пункта 1: меняем только функцию и ее вызов).
Ошибочное решение
void createDynArray(int *arr, int &size)
{
std::cout << "Введите размер массива: ";
std::cin >> size; // получить размер массива
arr = new int[size]; // выделить память под массив
for (int i{}; i < size; i++) arr[i] = i; // заполнить массив данными
}
// вызвать функцию, которая создаст динамический массив, заполнит его данными
// и вернет его адрес в вызывающую функцию; полученный адрес нужно сохранить
// в созданный выше указатель на массив
createDynArray(arr, size);
Программа с этим кодом аварийно заканчивает работу в тот момент, когда начинает выводить элементы созданного динамического массива в консоль. Позже, на свежую голову, я разобрался, в чем тут проблема.
Обычно студентам рассказывают, что есть три способа передать аргумент в функцию: по значению, по ссылке и по указателю. Способ «по значению» используется только для передачи данных внутрь функции, а способы «по ссылке» и «по указателю» используются и для передачи данных внутрь функции, и для возврата данных из функции.
В данном случае кажется, что мы используем способ передачи массива в функцию «по указателю» (поскольку параметр имеет указательный тип), а на самом деле тут - способ передачи «по значению» (в результате функция ничего не возвращает назад, программа пытается вывести массив по указателю arr, который мы проинициализировали значением nullptr; то есть выводить нечего, а программа пытается вывести и аварийно завершает работу).
Почему это так? В данном случае заковыка в том, что мы хотим передать «по указателю» массив, а имя массива само по себе является указателем на первый элемент этого массива. Чтобы здесь использовать способ передачи массива «по указателю», нужно использовать указатель на указатель.
Правильное решение
void createDynArray(int **arr, int &size)
{
std::cout << "Введите размер массива: ";
std::cin >> size; // получить размер массива
*arr = new int[size]; // выделить память под массив
for (int i{}; i < size; i++) (*arr)[i] = i; // заполнить массив данными
}
// вызвать функцию, которая создаст динамический массив, заполнит его данными
// и вернет его адрес в вызывающую функцию; полученный адрес нужно сохранить
// в созданный выше указатель на массив
createDynArray(&arr, size);
Обратите внимание, что при этом способе работы с массивом к указателю arr внутри функции приходится применять операцию разыменования, а при вызове функции к указателю arr приходится применять операцию взятия адреса.
Результат работы полученной программы в консоли будет такой же, как и в пункте 1 (при возврате динамического массива с помощью команды return).