0 / 0 / 0
Регистрация: 18.11.2014
Сообщений: 18

Освобождение памяти для объектов производного класса

23.11.2015, 19:56. Показов 3230. Ответов 8

Author24 — интернет-сервис помощи студентам
Всем привет. Не могу найти инфу в интернете, всё перерыл, но понял что случай специфичный у меня. Придумал себе конструкцию, но не уверен, что она работоспособна. Пока далеко не ушёл, решил задать вопрос. Часть кода:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        buildings - родительский класс с виртуальными функциями.
        motherbase - производный класс.
 
        buildings* motherbase::build()
 
    {
 
        motherbase* myMotherbase = new motherbase;
        return myMotherbase;
            
    } // метод производного класса возвращающий указатель на объект базового класса
 
        buildings** array1 = new buildings* [1]; // не спрашивайте зачем массив для одного значения =) 
    buildings** array2 = new buildings* [2]; // массив куда буду пихать все производные объекты от потомков класса buildings
    motherbase* MyBase = new motherbase; // создаю новый объект производного класса, выделяю память
    array1[0] = MyBase; // пихаю этот объект в массив1
        array2[0] = MyBase->build(); // через созданный объект вызываю функцию возвращающую указатель на объект базового класса и пишу во второй массив новый независимый объект
Ну и дальше через массивы я уже вызываю нужные мне функции из нужных объектов, меняю там значения, все дела. Собственно, вопросы:

1. Как очистить память в buildings* motherbase::build(). Вычитал, что если после return поставить delete myMotherbase, то это будет меморилик.
2. Когда в конце функции в которой созданы эти указатели ставлю delet [] array1 и 2, то деструктор не вызывается. Полагаю, память не освобождается.
3. Когда я ставлю delete MyBase, всё хорошо. Но если предварительно MyBase = 0; и только потом delete, то опять же деструктор не вызывается.
4. Пробовал возвращаться не указатель, а просто объект базового класса (MyBase уже не указатель, а motherbase MyBase) и писать его так array2[0] = &MyBase.build(); но тогда вызываются функции родительского класса, так что пришёл к выводу, что нужно возвращать указатель. Во всех остальных случаях краши.

Я так полагаю, что я не совсем вкурил механизм работы указателя на указатель на базовый класс. Помогите пожалуйста. VS2012, Win 7.

P.S. возможно слишком сложная конструкция buildings** array1 = new buildings* [1];

но мне принципиально важно иметь массив, который бы хранил объекты производного класса и я не нашёл как по-другому сделать. Ну и к тому же хочется разобраться в вопросах работы new, delete.
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
23.11.2015, 19:56
Ответы с готовыми решениями:

Освобождение памяти для члена класса
Добрый вечер :victory: Проблема, чувствую, тривиальная, но что-то я не могу сообразить :coffee2: В моём самописном классе есть член...

Освобождение памяти динамически созданных объектов
Подскажите, есть к примеру три класса: Class1, Class2, Class3. В Class2 имеется метод, в котором динамически создаю объекты класса...

Освобождение памяти из под Объектов в статическом массиве указателей
Всем добрый вечер! Решил расширить программу из книжки Лафорте Р. ООП в С++ стр. 574 путем добавления функции удаления данных о конкретном...

8
249 / 219 / 63
Регистрация: 30.07.2013
Сообщений: 465
23.11.2015, 20:31
Используй умные указатели, Люк!
0
0 / 0 / 0
Регистрация: 18.11.2014
Сообщений: 18
23.11.2015, 20:46  [ТС]
Не дорос =( мне бы это освоить, потом уже дальше двигаться. Я так не пойму ничего, если основы избегать.
0
249 / 219 / 63
Регистрация: 30.07.2013
Сообщений: 465
23.11.2015, 20:57
ОК.
Цитата Сообщение от Pseudodog Посмотреть сообщение
Как очистить память в buildings* motherbase::build()
motherbase::build() создает объект в куче, если там же будет очищаться память, что же будет возвращать эта функция? Нет, так не получится.
Цитата Сообщение от Pseudodog Посмотреть сообщение
если после return поставить delete
После return код не выполняется.
Цитата Сообщение от Pseudodog Посмотреть сообщение
ставлю delet [] array1 и 2
Этим ты уничтожаешь указатели на buildings (т.к. это элементы array), но не объекты, на которые указывают эти указатели.
Цитата Сообщение от Pseudodog Посмотреть сообщение
если предварительно MyBase = 0; и только потом delete, то опять же деструктор не вызывается
Конечно: указатель уже никуда не указывает, у кого delete деструктор вызывать будет?
Цитата Сообщение от Pseudodog Посмотреть сообщение
Пробовал возвращаться не указатель, а просто объект базового класса ... но тогда вызываются функции родительского класса
Потому что возвращается именно объект базового класса.

Короче, виртуальные функции обеспечивают полиморфирм при вызове через указатель или ссылку.
А удалять объкты в куче надо оператором delete. Т.е. пункт 3, но сначала detele, потом обнуление.
1
0 / 0 / 0
Регистрация: 18.11.2014
Сообщений: 18
23.11.2015, 22:36  [ТС]
Fyret, спасибо, ценные вещи.
Забыл что после return ничего не работает.

Но всё равно осталось 2 вопроса:

1. "Этим ты уничтожаешь указатели на buildings (т.к. это элементы array), но не объекты, на которые указывают эти указатели." т.е. я правильно понял, что написав delet [] array1 я всё же освобождаю память и бог с ним что нет деструктора, его и не должно быть?
2. Как освободить память выделенную в

C++
1
2
3
4
5
6
7
8
buildings* motherbase::build()
 
{
 
motherbase* myMotherbase = new motherbase;
return myMotherbase;
 
}
по человечьи при том что до передачи её нельзя возвращать? Я пробовал в паблике определять указатель на базовый класс, потом ему память давать в конструкторе, в деструкторе высвобождать, а при помощи build() возвращать объект и присваивать массиву. Компилилось на ура, но при попытке создать объект родительского класса конструктор вызывался бесконечно, ну и потом крашился.
0
249 / 219 / 63
Регистрация: 30.07.2013
Сообщений: 465
23.11.2015, 22:47
1. Нет.
C++
1
2
3
4
buildings** array2 = new buildings* [2]; // выделяется память для 2-х указателей
array2[0] = MyBase->build(); // выделяется память под объект и создается объект, т.е. вызывается конструктор
array2[1] = MyBase->build(); // аналогично
delete[] array2; // освобождается память из-под 2-х указателей
А 2 сконструированных объекта и память, занимаемая ими, остаются. Причем без возможности получить к ним доступ. Привет, memory leak.

2. Через delete. motherbase::build() создает объект и отдает указатель на него. Все, motherbase::build() больше не владеет этим объектом, не его забота, что там будет с этим объектом. Тот, кто владеет, тот и уничтожает.
C++
1
2
3
4
array2[0] = MyBase->build();
// всякое использование array2[0]
delete array2[0];
array2[0] = nullptr;
3. Конструктор, вызывающий сам себя, конечно же породит бесконечную рекурсию.
1
0 / 0 / 0
Регистрация: 18.11.2014
Сообщений: 18
23.11.2015, 22:53  [ТС]
Цитата Сообщение от Fyret Посмотреть сообщение
А 2 сконструированных объекта и память, занимаемая ими, остаются. Причем без возможности получить к ним доступ. Привет, memory leak.
Т.е. как я и думал конструкция убога =( Один из примеров вычитал тут: http://seliseev.ru/%D0%BC%D0%B... D0%B2-cpp/

там тоже возвращается родительский объект и тоже не возвращается память. Неужели кроме смартпоинтеров нет возможности забабахать нормальный менеджер создания объектов, что б без утечек? Как-то же обходились раньше.
0
249 / 219 / 63
Регистрация: 30.07.2013
Сообщений: 465
23.11.2015, 23:05
Лучший ответ Сообщение было отмечено Pseudodog как решение

Решение

Так вариантов-то всего 2: либо ручное управление памятью, либо RAII, т.е. смарт-поинтеры в частности.
Ну если не хочется смарт-поинтером, можно заюзать идиому Pimpl. Но поинтеры проще.
1
0 / 0 / 0
Регистрация: 18.11.2014
Сообщений: 18
23.11.2015, 23:07  [ТС]
Fyret, спасибо большое за ответ, тогда изучаю дальше =)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
23.11.2015, 23:07
Помогаю со студенческими работами здесь

Освобождение памяти в методе класса
Здравствуйте, В университете дали задание написать написать стек с итератором произвольного доступа. Собственно, класс стека и итератора...

Освобождение памяти от экземпляра класса
есть класс : Message есть контейнер типа : multimap<int,Message> myQueue этот контейнер формируется так Message *c_message = new...

Освобождение памяти в деструкторе класса
Перечитал по этому поводу много информации. Главный вопрос. Есть класс в котором происходит динамическое выделение памяти. В...

Освобождение памяти членов структуры(класса)
Всем привет! Ситуация: struct S1 { char * Data; S1() {

Поменять make и release так, чтобы организовать правильное уничтожение объектов и освобождение памяти
Имеем код: #include <iostream> struct Base { public: ~Base() { std::cout << "Base::~Base" << std::endl; } ...


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

Новые блоги и статьи
Вопросы на собеседованиях по микросервисам
ArchitectMsa 27.03.2025
Работодатели ищут не просто разработчиков, знающих базовые концепции, а специалистов, разбирающихся в тонкостях масштабирования, отказоустойчивости и производительности. Сейчас на первый план выходят. . .
Взаимодействие Python с REST API
py-thonny 27.03.2025
REST API - это архитектурный стиль взаимодействия компонентов распределённого приложения в сети. Python располагает функциональным набором инструментов для работы с REST API и основная библиотека для. . .
sshd restrictions, ssh access limitations
jigi33 26.03.2025
sshd restrictions | ssh access limitations рестрикции доступа на сервер sshd статья: https:/ / www. golinuxcloud. com/ restrict-allow-ssh-certain-users-groups-rhel
Компиляция C++ с Clang API
NullReferenced 24.03.2025
Компиляторы обычно воспринимаются как черные ящики, которые превращают исходный код в исполняемые файлы. Мы запускаем компилятор командой в терминале, и вуаля — получаем бинарник. Но что если нужно. . .
Многопоточное программировани­е в C#: Класс Thread
UnmanagedCoder 24.03.2025
Когда запускается приложение на компьютере, операционная система создаёт для него процесс - виртуальное адресное пространство. В C# этот процесс изначально получает один поток выполнения — главный. . .
SwiftUI Data Flow: Передача данных между представлениями
mobDevWorks 23.03.2025
При первом знакомстве со SwiftUI кажется, что фреймворк предлагает избыточное количество механизмов для передачи данных: @State, @Binding, @StateObject, @ObservedObject, @EnvironmentObject и другие. . . .
Моки в Java: Сравниваем Mockito, EasyMock, JMockit
Javaican 23.03.2025
Как протестировать класс, который зависит от других сложных компонентов, таких как базы данных, веб-сервисы или другие классы, с которыми и так непросто работать в тестовом окружении? Для этого и. . .
Архитектурные паттерны микросервисов: ТОП-10 шаблонов
ArchitectMsa 22.03.2025
Популярность микросервисной архитектуры объясняется множеством важных преимуществ. К примеру, она позволяет командам разработчиков работать независимо друг от друга, используя различные технологии и. . .
Оптимизация рендеринга в Unity: Сортировка миллиона спрайтов
GameUnited 22.03.2025
Помните, когда наличие сотни спрайтов в игре приводило к существенному падению производительности? Время таких ограничений уходит в прошлое. Сегодня геймдев сталкивается с задачами совершенно иного. . .
Образование и практика
Igor3D 21.03.2025
Добрый день А вот каково качество/ эффективность ВУЗовского образования? Аналитическая геометрия изучается в первом семестре и считается довольно легким курсом, что вполне справедливо. Ну хорошо,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru