Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.63/40: Рейтинг темы: голосов - 40, средняя оценка - 4.63
70 / 70 / 35
Регистрация: 06.07.2016
Сообщений: 415

Выделение памяти для динамического двумерного массива внутри функции

11.08.2017, 00:09. Показов 8122. Ответов 25
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Имеется вот такой код :
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
 
void allocateMemory(int ***array, int size);
void freeMemory(int **array, int size);
int main()
{
    int **matrix{ nullptr };
    constexpr int size{ 10 };
    allocateMemory(&matrix, size);
    freeMemory(matrix, size);
}
 
void allocateMemory(int ***array, int size)
{
    *array = new int *[size];
    for (int index{ 0 }; index < size; index++)
    {
        (*array)[index] = new int[size];
    }
}
 
void freeMemory(int **array, int size)
{
    for (int index{ 0 }; index < size; index++)
    {
        delete[] array[index];
    }
    delete[] array;
}
Он работает, память выделяет, если верить VS и rexster(GCC), даже чистит её.
Но я вот усиленно не могу понять, почему не работает такой вариант :
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void allocateMemory(int **array, int size)
{
    array = new int *[size];
    for (int index{ 0 }; index < size; index++)
    {
        array[index] = new int[size];
    }
}
int main()
{
    int **matrix{ nullptr };
    constexpr int size{ 10 };
    allocateMemory(matrix, size);
    freeMemory(matrix, size);
}
После возвращения из allocateMemory в таком случае matrix имеет значение nullptr, а значит, указатель на указатель передается по значению, но ведь его значение - и есть адрес указателя, указывающего на int.
Ведь имя массива - и есть адрес его первого элемента и идет передача значения, которое является адресом, то есть того, что нам нужно. По крайне мере, это работает на одномерных массивах. А вот здесь - ступор.
Причем работает и такой вариант функции освобождения памяти :
C++
1
2
3
4
5
6
7
8
void freeMemory(int ***array, int size)
{
    for (int index{ 0 }; index < size; index++)
    {
        delete[] (*array)[index];
    }
    delete[] *array;
}
Честно сказать, просто уже запутался с этими указателями на указатели, которые передаются не так, как хочется.
Около полугода назад встречался с похожим, но тогда проблему исправил методом тыка и как-то забылось. Сейчас совершенно случайно всплыло снова, причем со 2го раза также все удачно написалось, но суть проблемы я понимаю не очень. А это ведь еще даже не С++, а С, то есть совсем уже базовый уровень.
Разъясните, пожалуйста, как можно подробнее, в чем же здесь кроется секрет.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
11.08.2017, 00:09
Ответы с готовыми решениями:

Выделение памяти для двухмерного массива внутри функции
Здравствуйте. Предположим, есть код: #include &lt;iostream&gt; #include &lt;iomanip&gt; #include &lt;cstdlib&gt; #include &lt;time.h&gt; ...

Как правильно записать в виде функции выделение памяти для двумерного массива и ее освобождение
Здравствуйте! Подскажите, как правильно записать в виде функции выделение памяти для двумерного массива и ее освобождение. ...

Выделение памяти для двумерного массива
Обьясните что означает double** A = new double*, A = new double;,cout.precision(2);, delete A;?????? #include &lt;iostream&gt; ...

25
70 / 70 / 35
Регистрация: 06.07.2016
Сообщений: 415
19.08.2017, 23:13  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от DrOffset Посмотреть сообщение
переменной типа "массив"
Быть может я вас неправильно таки понял. Но если существует конкретный тип массив, почему нельзя сделать вот так :
C++
1
int [] returnArray() {}
Понятное дело, что можно сделать так, как я всегда и делал, даже не задумываясь особо :
C++
1
int* returnArray() {}
Невозможно вернуть переменную типа массив, так как невозможно автоматическое приведение типа от массива к указателю для передачи обратно именно адреса?
Или же это сделано для защиты от возвращения из функции локального массива, который уничтожится после ее выполнения?
Или же я что-то не так понимаю?
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
19.08.2017, 23:30
Цитата Сообщение от Notoriously Посмотреть сообщение
Но если существует конкретный тип массив, почему нельзя сделать вот так
Так нельзя сделать, потому что по историческим, и, вероятно, идеологическим причинам тип "массив" в С++ (и в С) не порождает объекты первого класса. Это значит, что "массив" обладает неполным набором операций, и в частности не обладает возможностью копировать по значению свои объекты. В С и С++ есть еще один такой тип - это "функция".

Добавлено через 8 минут
Notoriously, в с++11 (а до этого в boost) появился шаблон std::array, который инкапсулирует массив с возможностью копирования по значению. Вот с ним можно написать так:
C++
1
2
3
4
std::array<int, 10> returnArray() {
    std::array<int, 10> arr = {1,2,3,4};
    return arr;
}
И еще небольшое замечание, даже если бы возврат по значению массива был возможен непосредственно, то синтаксис был бы не совсем такой, как ты показал, а вот такой:
C++
1
int ( returnArray() )[10]; // подобным же образом выглядел бы возврат ссылки на массив int (& returnArray() )[10] или указателя на массив int ( * returnArray() )[10] - эти записи разрешены
Если мы попробуем скомпилировать этот код, то получим диагностику, указывающую на то, о чем я выше говорил:
error: function cannot return array type 'int [10]'
1
70 / 70 / 35
Регистрация: 06.07.2016
Сообщений: 415
19.08.2017, 23:43  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
в с++11 (а до этого в boost) появился шаблон std::array,
Да, про него знаю. Но использовать STL когда еще не до конца понимаешь языковых конструкций, бывших еще даже в языке С - не хочется.
Цитата Сообщение от DrOffset Посмотреть сообщение
то синтаксис был бы не совсем такой, как ты показал, а вот такой:
Не такой страшный, как при работе с функциями в качестве параметров, но все же не очень интуитивно понятный.

Спасибо, значит понимал правильно, но вот про такие вещи как объекты первого класса и что вообще для определенного типа в языке был ограничен набор применимых операций - слышу впервые.
Эти нюансы упоминаются только в стандарте?
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
19.08.2017, 23:56
Цитата Сообщение от Notoriously Посмотреть сообщение
Эти нюансы упоминаются только в стандарте?
В стандарте лишь перечислены ограничения для типа.
Терминология такая там не используется, это более общие понятия - кросс-языковые. Это просто удобное обозначение, которое хорошо согласуется с наблюдаемым поведением.

Добавлено через 3 минуты
Цитата Сообщение от Notoriously Посмотреть сообщение
Но использовать STL когда еще не до конца понимаешь языковых конструкций, бывших еще даже в языке С - не хочется.
Можно написать такой класс самостоятельно, он очень простой:
C++
1
2
3
4
5
6
7
8
template <typename T, size_t N>
struct array
{
    T & operator[](size_t i) { return m_array[i]; }
    T const & operator[](size_t i) const { return m_array[i]; }
 
    T m_array[N];
};
1
70 / 70 / 35
Регистрация: 06.07.2016
Сообщений: 415
21.08.2017, 01:23  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Можно написать такой класс самостоятельно
Да, уже делал, спасибо. Вот только мне усиленно казалось, что в качестве размера N можно передать неконстантное выражение и получить "VLA" (как я вычитал в интернете) массив, поэтому я std :: array активно пренебрегал. Но сейчас вот попробовал на GCC и в таком случае компилятору это всегда получается отследить.
Причем вот так он сделать дает : (я так понимаю, получаем VLA) :
C++
1
2
3
4
5
6
7
8
#include <iostream>
 
int main()
{
    int capacity;
    std :: cin >> capacity;
    int array[capacity];
}
А вот так, оказывается, нет :
C++
1
2
3
4
5
6
7
8
9
#include <iostream>
#include <array>
 
int main()
{
    int capacity;
    std :: cin >> capacity;
    std :: array <int, capacity>;
}
Спасибо за помощь и информацию.
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
21.08.2017, 08:30
Цитата Сообщение от Notoriously Посмотреть сообщение
Причем вот так он сделать дает
Так он сделать дает из-за расширения GCC для массивов - в стандартном С++ так делать тоже нельзя.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
21.08.2017, 08:30

Динамическое выделение памяти для двумерного массива
нужна помощь вот тело программы, не могу сделать динамическое выделение памяти для первого двумерного массива. второй массив получается...

Выделение динамической памяти для двумерного массива.
#include &lt;iostream&gt; int main() { setlocale( LC_ALL,&quot;Russian&quot; ); int N, M; std::cout &lt;&lt; &quot;Введите кол-во строк в массиве:...

Если выделение памяти для динамического массива задать void-функцией, можно ли будет оперировать с ним в main?
Если выделение памяти для дин.массива задать void-функцией, можно ли будет оперировать с ним в main или придётся отдельно выделять память в...

Вызов функции динамического выделение памяти
Здравствуйте! Нужна помощь! Написал функцию выделение памяти под двумерный динамический массив, которая возвращает масив размером...

Инициализация двумерного динамического массива внутри программы
Здравствуйте! Подскажите, пожалуйста, можно ли как-то инициализировать двумерный динамический массив значениями без ввода при запуске?...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
26
Ответ Создать тему
Новые блоги и статьи
Копировать Windows на новый диск на UEFI
damix 17.10.2026
https:/ / uriesk. wordpress. com/ 2016/ 11/ 01/ move-window-10-to-ssd-on-a-uefi-dualboot-system-with-basic-linux-tools/ TL DR Вставляем диск, а старый подключаем через переходник, грузимся с лайва. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru