Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
0 / 0 / 0
Регистрация: 25.07.2020
Сообщений: 36

Функция принимает указатель на динамический массив переданный другой функцией. Как правильно освободить память?

25.07.2020, 05:08. Показов 1399. Ответов 5

Студворк — интернет-сервис помощи студентам
Подскажите, пожалуйста, начинающему!

Есть функция-член в одном классе, которая создаёт при помощи new динамический массив (скажем размерности [2], хотя это частный случай) и возвращает в др. функцию
friendly класса. Во втором классе есть массив размерности [2] с корректным типом значений (таким же как в отдающей функции)
Вторая функция принимает указатель на массив и с его помощью присваивает значения фиксированному по размеру массиву своего класса.
Для этого в main() сначала создаётся объект первого класса "Deck" т.е. колода на 52 карты, потом создаётся объект "Hand" т.е. "рука" игрока на 2 карты и выделенный в тексте листинга main вызов функции gethand() (объекта класса hand) получает указатель от функции DrawXCards объекта "Deck" и по указателю заполняет [2] массив данных своего объекта.
(Может путанно объяснил, но не знаю как проще).

Как и когда в таком случае правильно освободить память с помощью delete[] занятую созданным динамическим массивом и чем чревато, если этого не сделать? Память остаётся занятой даже после выхода из программы?
Просто получается, что отдающая функция уже отработала и закрылась, а принимающая по полученному указателю заполнила значения массива своего объекта. А как и когда освободить память того созданного динамического массив на который пришёл указатель для заполнения никак не могу понять.

Первый класс и передающая функция DrawXCards():

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
30
31
32
33
34
35
36
37
class DECK 
{
private:
    CARD deck[52];
 
public:
    DECK() 
    {
 
        int k = 0;
 
        for (int i=1; i<=4; i++) 
        {
            for (int j = 2; j <= 14; j++) { deck[k].value = static_cast<VALUE>(j); deck[k].suit = static_cast<SUIT>(i); k++; }
        }
    
    }
 
    void Show() const;
    void Shuffle();
    void Order();
    CARD* DrawHand() const;
    CARD* DrawXCards(unsigned int start, unsigned int offset, unsigned int number) const;
 
    friend class HAND;
};
 
[B]CARD* DECK:: DrawXCards(unsigned int start, unsigned int offset, unsigned int number) const[/B]
{
    CARD* array = new CARD[number];
    unsigned int base = start + offset;
 
    for (int i = 0; i < number; i++) { array[i] = deck[base++]; }
    return array;
    
 
}
Второй класс и принимающая функция gethand():
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
class HAND 
{
private:
    CARD hand[2];
 
public:
 
    HAND() 
    {
        hand[0].value = EMPTY; 
        hand[0].suit = NOSUIT; 
        hand[1].value = EMPTY; 
        hand[1].suit = NOSUIT;
    }
 
    [B]void gethand(CARD* array)[/B]
    { 
        hand[0] = array[0];
        hand[1] = array[1];
 
        
    }
 
    void display() const;
 
};
Main():
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int main () 
{
    char ch = ' ';
 
    DECK deck1;
    HAND hand1;
    
    
 
        deck1.Shuffle();
        cout << endl;
 
        deck1.Show();
 
        [B]hand1.gethand(deck1.DrawXCards(0,0,2));[/B]
        hand1.display();
        
        cout << endl;
 
    
 
    return 0;
}
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
25.07.2020, 05:08
Ответы с готовыми решениями:

Функция принимает указатель на динамический массив и возвращает его же, но без чисел полиндромов (читается с обоих сторон одинаково - 234432)
Вот мое решение, подскажите, пожалуйста, что изменить, чтобы заработала программа: # include &lt;iostream&gt; # include...

Ввести в динамический массив 100 вещественных чисел, вывести их в обратном порядке, освободить память
Задание: Ввести в динамический массив 100 вещественных чисел, вывести их в обратном порядке, освободить память. набрал непойму почему...

Как правильно освободить память
Здрасте! (Тема: Шаблоны функций.) Не могу правильно написать метод для освобождения памяти. В мейне делаю все необходимые мне...

5
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
25.07.2020, 06:09
Здесь нужен объект-обертка аналогичный std::vector, который будет владеть динамическим массивом и подчищать его. Или сам std::vector.
Но я бы лучше предложил влепить в DrawXCards аргумент CARD* array, чтобы он выводил данные сразу в HAND. Без всех этих операций с динамической памятью.
1
0 / 0 / 0
Регистрация: 25.07.2020
Сообщений: 36
25.07.2020, 06:41  [ТС]
Цитата Сообщение от Renji Посмотреть сообщение
Здесь нужен объект-обертка аналогичный std::vector, который будет владеть динамическим массивом и подчищать его. Или сам std::vector.
Но я бы лучше предложил влепить в DrawXCards аргумент CARD* array, чтобы он выводил данные сразу в HAND. Без всех этих операций с динамической памятью.
К сожалению про вектора и обёртки ничего не знаю. Пока не дошёл до этого. Владею только массивами и указателями, вернее только начинаю овладевать.
По поводу аргумента CARD* array в DrawXCards вы имеете ввиду static массив на [2] элемента, который бы "висел" в памяти всю программу? Но как к нему получит доступ функция gethand() из класса Hand для заполнения своего массива? Он же, этот аргумент, получается будет статичной локальной переменной локализованной внутри функции DrawXCards!?
Или имеется ввиду добавить аргумент в скобки функции DrawXCards в виде самого массива CARD[2] из объекта hand, который передаём по ссылке в DrawXCards и она его напрямую заполняет? Тогда я понимаю, но просто это решение годится, когда известна длина массива т.е. сколько элементов в него копировать из объекта Deck.
И потом нарушается иерархия построения классов. Получается не класс Hand вытаскивает себе карты из Deck, а наоборот класс Deck из которого тянутся карты "лезет" своей функцией напрямую в соответствующий массив класса hand, в который эти карты должны попадать. Или я чего то не понимаю.

Можно поподробней, я не очень понял, где должен быть данный аргумент и как он будет передаваться в массив размера [2] объекта класса Hand.

И потом это получается не универсальное решение, потому что вдруг мы захотим "вытащить" из колоды не 2 карты а 3 или 4 и запихнуть уже в объект другого класса с массивом данных бОльшей размерности того же класса Card.

А нельзя ли в main создать промежуточный указатель типа CARD* ptr, затем присвоить ему возврат функции DrawXCards,
потом вызвать hand1.gethand(ptr), чтоб заполнить массив, который находится в hand1, потом все нужные действия и в конце сделать просто
delete[] ptr; ?

Это не очистит динамическую память?
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
25.07.2020, 06:53
Лучший ответ Сообщение было отмечено realalexandro как решение

Решение

Цитата Сообщение от realalexandro Посмотреть сообщение
А нельзя ли в main создать промежуточный указатель типа CARD* ptr, затем присвоить ему возврат функции DrawXCards
Можно. Только это си-стайл будет, а не ООП.
Цитата Сообщение от realalexandro Посмотреть сообщение
Или имеется ввиду добавить аргумент в скобки функции DrawXCards виде самого массива CARD[2] из объекта hand, который передаём по ссылке в DrawXCards и она его напрямую заполняет?
Не CARD[2], а именно CARD*. Любой одномерный массив можно привести к указателю на один элемент.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void test(int*array,int size)//функция принимает указатель на int
{
    for(int i=0;i<size;++i)
        array[i]=i;
}
int main()
{
    int array1[10];
    int array2[30];
    //а передать можно массив любого размера
    test(array1,10);
    test(array2,30);
    return 0;
}
Цитата Сообщение от realalexandro Посмотреть сообщение
Получается не класс Hand вытаскивает себе карты из Deck, а наоборот класс Deck из которого тянутся карты "лезет" своей функцией напрямую в соответствующий массив класса hand, в который эти карты должны попадать.
Ну, можно наоборот.
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
class Hand;
class Deck
{
    friend class Hand;
public:
private:
    int data[52];
};
 
class Hand
{
public:
    //класс Hand лезет в класс Deck
    Hand(Deck&deck,std::size_t pos):data{deck.data[pos],deck.data[pos+1]}{}
private:
    int data[2];
};
 
int main()
{
    Deck deck;
    Hand hand(deck,0);
    return 0;
}
0
0 / 0 / 0
Регистрация: 25.07.2020
Сообщений: 36
25.07.2020, 07:16  [ТС]
Цитата Сообщение от Renji Посмотреть сообщение
Ну, можно наоборот.
Ага! Вот это я понял теперь логику т.е. объект hand в своём конструкторе сразу получает по ссылке параметр-объект
класса Deck и "тянет" из него карты с нужными номерами по индексам. Одно уточнение. А что за тип "size_t" pos
(почему просто int не использовать, это же параметр стартового индекса массива с которого начинаем операцию?)
и зачем добавлять указатель на пространство имён если в самом начале уже написано using namespace std; ?
Я правда это сделал бы не в конструкторе, а в отдельной функции заполнения hand, поскольку в один объект hand будут в цикле много пар карт потом закидываться, - не создавать же каждый раз новый объект.
Но всё равно спасибо огромное, что помогли!

Цитата Сообщение от Renji Посмотреть сообщение
Можно. Только это си-стайл будет, а не ООП.
Ну да, тут вы правы на 100%. Правда это только одна инструкция. Всё остальное то в ООП парадигме написано.
Но память то главное очищается таким образом? Я вот просто не понимаю, если под new[] не будет delete[], что собственно случится?
Оперативка забьётся после окончания работы программы? Или в процессе работы только? Сорри, вопрос, наверное идиотский, но не знаю механизма просто...
Ещё раз большое спасибо!
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
25.07.2020, 07:21
Цитата Сообщение от realalexandro Посмотреть сообщение
Одно уточнение. А что за тип "size_t" pos
(почему просто int не использовать, это же параметр стартового индекса массива с которого начинаем операцию?)
size_t это тип из #include<cstddef>. int нельзя использовать потому что 1) для int не гарантируется что в него влезет максимально возможный в сишном массиве индекс. Для size_t гарантируется. 2) int знаковый. Использовать знаковый тип для заведомо беззнакового смещения как-то не очень корректно.
Цитата Сообщение от realalexandro Посмотреть сообщение
Я вот просто не понимаю, если под new[] не будет delete[], что собственно случится?
Память будет занята до завершения программы. Потом все захваченные ресурсы будут отобраны у нее принудительно.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
25.07.2020, 07:21
Помогаю со студенческими работами здесь

Как правильно освободить память
Есть функция char* md5(const char*). Как освободить память выделенную ею? #include &lt;openssl\md5.h&gt; char* md5(const char* text) { ...

Как правильно освободить память
Здравствуйте все! Подскажите, как правильно освобождать память, выделенную под массив оператором new? int *Arr = new int; ... delete...

Как правильно освободить память
Написал вот такой костыль: wchar_t* getDate() { time_t seconds = time(NULL); tm timeinfo = *(localtime(&amp;seconds)); return...

Как правильно выделить память под двумерный динамический массив
подскажите как правильно выделить память под двумерный динамический массив?

Как правильно освободить память в QHash?
Добрый день. Не могу разобраться с парой вопросов. Выделяю память под объект Client, потом этот указатель на объект помещаю в QHash с...


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

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru