Форум программистов, компьютерный форум, киберфорум
ООП и паттерны
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.50/4: Рейтинг темы: голосов - 4, средняя оценка - 4.50
0 / 0 / 0
Регистрация: 26.10.2015
Сообщений: 9
1

Фабрики и new/delete

05.01.2016, 13:43. Просмотров 681. Ответов 9
Метки нет (Все метки)

С++. Есть тяжёлый текстовый контейнер, который должен создаваться фабрикой (в моём случае это наверное Строитель), а в итоге будет передан в обработчик для проделывания там с ним всякого (readonly).

По идее же фабрики не хранят указатели на создаваемые в них объекты. То есть сделали new, выплюнули клиентскому коду и забыли, а там, где был запрос фабрике на создание, должен быть код на удаление.

Но. Вот например сам контейнер. Сначала в кучу был залит сырой текст отдельным new. Потом другим new сделан пустой контейнер, которому в конструктор был передан указатель на сырой текст. А потом ведь фабрика выплёвывает контейнер на верх и отказывается от всех своих new. Это значит, что в контейнере, которому подкинули указатель на сырой текст, нужно сделать его удаление. А это выглядит подозрительно не здоровым. Тем более, что Макконнелл в Совершенном коде пишет, что надо удалять в той же области видимости, где было создано. Получается, что такой контейнер нельзя будет использовать отдельно от фабрики, ну или на свой страх и риск только. Как-то это не освещено в книжке банды GoF.

Как быть?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
05.01.2016, 13:43
Ответы с готовыми решениями:

Написать аналог процедуры Delete. Процедурой Delete и функцией Copy не пользоваться
Написать аналог процедуры Delete. Процедурой Delete и функцией Copy не пользоваться. кто сможет?...

Используя delete по указателю, возвращенному new [] или delete [] указателем, возвращаемым new
Помогите ответить на вопрос, не могу понять суть вопроса (правильно ли понимаю, что будет если...

В чем разница между delete и delete[]?
а можете еще по подробней рассказать про delete, точнее даже delete, чем именно отличается delete...

Какая разница между delete и delete[]
Нашел информацию на разных сайтах и всё равно остались вопросы. Я понимаю, что delete используется...

9
Модератор
2608 / 1790 / 396
Регистрация: 26.03.2015
Сообщений: 6,610
05.01.2016, 15:42 2
Не понятно, какой смысл Вы вкладываете в "текстовый контейнер". Не похоже, что у Вас там вектор строк.
И что такое "сырой текст" и каким образом его залили в кучу - тоже непонятно.
Гадать не хочется, а телепаты в отпуске.
0
2883 / 1964 / 335
Регистрация: 24.11.2012
Сообщений: 4,772
05.01.2016, 16:04 3
vipermagi, как было сказано выше, задача непонятна. Пока можно только сказать, что без острой необходимости не нужно управлять памятью вручную, для этого есть умные указатели.
0
0 / 0 / 0
Регистрация: 26.10.2015
Сообщений: 9
07.01.2016, 02:01  [ТС] 4
В текстовом контейнере содержится во-первых массив "сырого" UCS4-текста 4-байтных целых беззнаковых, во-вторых данные анализа, в-третьих итератор. На данный момент "сырой" текст просто грузится из файла. "Сырой" всмысле "raw". Сырее только массив байтов. Он даже на строки не разбит. Где-то сейчас читал, кто-то назвал такой текст "голый".

Есть некий менеджер, в котором происходит выбор какой будет реализация текстового контейнера. Менеджер получает свой готовый объект потому, как заказывал. А дальше, по логике, пользователю нужно с этим объектом работать. Это значит, что текстовый контейнер должен быть отдан менеджером в обработчик, которым будет управлять пользователь, и в котором будет происходить своя интерпретация всех действий с текстовым контейнером через итератор. С точки зрения менеджера и передачи в обработчик, здесь всё норм: менеджер удалит сам заказанный им текстовый контейнер после того, как обработчик закончит свои с ним дела.

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

Я планирую в конечном варианте не руками из файла грузить текст, а программно динамически из базы, т.е. совсем без участия пользователя. Будет это отдельный фабричный класс, возвращающий наверх указатель на вектор 4-хбайтных чисел, как и в прототипе программы при простой загрузке руками пользователя.

И так, вот менеджер заказывает у Строителя текстовый контейнер. Внутри строителя несколько последовательных этапов. Одним из этапов является создание объекта текстового контейнера с передачей в конструктор указателя на кусок "сырого" текста, который(указатель) только что был возвращён Строителю другим фабричным классом. То есть, одна фабрика создаёт "сырой" текст и передаёт владение другой фабрике, другая фабрика передаёт владение конечному контейнеру.

С точки зрения фабрик всё в порядке, они не должны запоминать созданные объекты. Но с точки зрения дизайна класса контейнера, он становится испорченным. Ведь в его деструкторе по RAII должно быть удаление принятого в конструкторе объекта. Такой текстовый контейнер можно будет использовать только в фабриках. А в алгоритме, где надо только временно поместить указатель в контейнер, объект попадёт в чёрную дыру и будет сегфолт.

Как спроектировать контейнер таким образом, чтобы он мог использоваться и для RAII с фабриками и обычным способом? Как сделать это всё более гибким? Принципы и паттерны проектирования они ведь именно про гибкость, а не про то, как сделать то, что очень очень хочется.

0x10, есть только std::auto_ptr, но если очень захотеть то и boost::shared_ptr. Смысл не в них. Смысл в том, что у меня аналог auto_ptr - это класс текстового контейнера. А он не просто оболочка для удаления, а полноценный класс. Смотришь вот на такой текстовый контейнер и совсем не ожидаешь, что это чёрная дыра для попадающих в него объектов.
0
2883 / 1964 / 335
Регистрация: 24.11.2012
Сообщений: 4,772
08.01.2016, 10:14 5
Для простоты предлагаю начать рассуждать с функций. Обсуждение паттернов приводит к добавлению лишних терминов, несущих в себе дополнительную семантику, которая пока не нужна.

Итак, у нас есть две сущности:
1. Text. Сырой текст, блоб, данные. Может быть получен из разных источников.
2. ITextWrapper. Обертка над текстом, «контейнер». Обертка выбирается независимо от блоба. Разным оберткам можно подавать на вход текст с одинаковым содержимым, и они будут совершать над ним разные операции.

Для каждой сущности нужна производящая функция:
1. Text* LoadText(); для загрузки текста из разных источников.
2. ITextWrapper* CreateWrapper(Text*); для оборачивания текста в «контейнер».

Контрольная точка. До сих пор я все правильно понимаю?

Проблема.
Память для Text выделяется в функции LoadText. После чего владение на Text передается в ITextWrapper. И это кажется сложным для понимания и неудобным: управление памятью распределено по разным частям приложения. Хочется упростить.

Контрольная точка. Правильно ли я понял проблему?

Ключевой момент выше — это «передача владения». Это и реализуестя на умных указателях. Ниже пример (text заменено на более общее data)
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
#include <iostream>
#include <memory>
 
std::unique_ptr<int> LoadData() {
    return std::unique_ptr<int>(new int(42));
}
 
struct DataWrapper {
    DataWrapper(std::unique_ptr<int> data)
    : data_(std::move(data)) {
    }
    
    std::unique_ptr<int> data_;
};
 
DataWrapper CreateWrapper(std::unique_ptr<int> data) {
    return DataWrapper(std::move(data));
}
 
int main() {
    std::unique_ptr<int> data = LoadData();
    DataWrapper dw = CreateWrapper(std::move(data));
    
    std::cout << *dw.data_ << std::endl;
}
Можно использовать shared_ptr, эффект будет примерно тем же, но код станет чуть проще (не понадобятся вызовы move).
1
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
08.01.2016, 11:05 6
0x10
Всё же, лучше никуда владение не передавать. Иначе потом начнут возникать проблемы... В одной библиотеке память выделили, а удалили в другой.
1
2883 / 1964 / 335
Регистрация: 24.11.2012
Сообщений: 4,772
08.01.2016, 11:15 7
mporro, да, и в этом случае опять же shared_ptr отработает нормально, т.к. по умолчанию освобождение памяти будет выполнено в той же единице трансляции, что и выделение.
0
0 / 0 / 0
Регистрация: 26.10.2015
Сообщений: 9
09.01.2016, 05:50  [ТС] 8
Точно ведь. Если через shared_ptr и делать new в его конструкторе, то можно потом в контейнер передавать тоже в shared_ptr на временную обработку. Тогда auto_ptr/unique_ptr здесь однозначно не подходят. Главное только не забыть, что shared_ptr нельзя инициализировать указателем при этом.

Вчера тоже читал, про корректную работу shared_ptr с библиотеками.

Я ещё немного подумал, возможно мне будет лучше загружать "сырой" текст снаружи фабричного класса, и передавать его туда указателем. Так как от его содержимого не зависит остальное наполнение контейнера. И для контроля загрузки менеджером в будущем удобнее. Что, конечно, не отменяет решение shared_ptr для остальных объектов в куче, созданных внутри фабричного класса, строящего текстовый контейнер.
0
2883 / 1964 / 335
Регистрация: 24.11.2012
Сообщений: 4,772
09.01.2016, 08:12 9
Цитата Сообщение от vipermagi Посмотреть сообщение
Если через shared_ptr и делать new в его конструкторе
На всякий случай напомню про функцию std::make_shared.
0
0 / 0 / 0
Регистрация: 26.10.2015
Сообщений: 9
11.01.2016, 13:33  [ТС] 10
Цитата Сообщение от 0x10 Посмотреть сообщение
На всякий случай напомню про функцию std::make_shared.
Мне такое не доступно.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
11.01.2016, 13:33

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Есть ли операторы new, new[], delete, delete[]
Есть ли операторы new, new, delete, delete в Си? И, если есть, чем они отличаются? Тихо...

Чем отличается delete[] от delete?
чем отличается? delete mas от delete mas

Паттерны проектирования (Фабрики)
Добрый вечер. Есть игра &quot;Морской бой&quot; из учебника Павловской Т.А . Задача: добавить в ней...

БД для мебельной фабрики
Добрый день, есть ли у кого нибудь исходник с БД на тему мебельная фабрика. Мне нужно написать...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.