| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Для новичков > +Выделение и освобождение памяти на разных уровнях |
| Автор: zim22 27.6.2009, 14:16 | ||||||
Выполняю задание из Страуструпа.
Функцию я написал:
Проблема в том, что однажды кто-то мне сказал, что память должна выделяться и освобождаться на одном уровне. скорей всего для того, чтобы пользователю не пришлось вручную удалять строку - т.к. он может забыть это сделать.
как тогда переписать функцию, чтобы удовлетворялось требование "уровня"? есть ли такое требование вообще? |
| Автор: zkv 27.6.2009, 14:32 |
| zim22, безусловно, так писать нельзя. А если копнуть глубже, то new вообще пользоваться не стоит. Полагаю, учебная задача? Так сделайте то, что вас просят, для себя главное отложите, что это неправильно. Можно подготовить два варианта: правильный и соответствующий заданию, при сдаче пояснить. Наверное так бы и поступил. PS Радует то, что такой вопрос родился, многие бы просто прошли мимо, сделав то, что их просят. |
| Автор: zim22 27.6.2009, 14:38 |
нет. задача не учебная. мне "для себя" необходимо понять, в чём ошибка "проектирования" метода и как её избежать. |
| Автор: Andrew121 27.6.2009, 14:54 |
| Я в таких случаях предварительно выделяю память, и передаю указатель. |
| Автор: zkv 27.6.2009, 15:00 |
| zim22, вы сами ответили на свой вопрос, есть необходимость использования new - используйте в там, где можно использовать и delete. В данном случае, память следует выделять за пределами функции cat, там же ее (память) и освобождать. Ну а если С++, то юзать чего нить типа boost::shared_ptr (который вроде ныне известен как std::tr1::shared_ptr). Хотя если совсем C++, то тут и подобной задачи не возникнет: есть сущность - реализуй ее классом. |
| Автор: maxim1000 27.6.2009, 17:23 |
| есть очень простой принцип, которому стоит следовать в большинстве (если не во всех) случаев: ответ на вопрос о владении объектом должен быть очевиден, всё остальное - способы достижения этой очевидности (под владением подразумевается, кто должен удалить этот объект) а способы такие: 1. стековые объекты 2. boost::shared_ptr, boost::scoped_ptr, std::auto_ptr 3. близость создания и удаления в коде 4. документация (имена функций, переменных, комментарии) (попробовал упорядочить по "степени надёжности", но это может быть субъективно) в некоторых случаях последний способ не так уж и страшен например, паттерн "фабрика" часто как раз и предполагает наличие метода, который создаёт объект, но удалением занимается кто-то другой (возможно, даже не метод этой фабрики) использовать умные указатели на этом уровне не всегда хорошо, т.к. каждый тип умного указателя навязывает свою стратегию владения, а иногда это решение стоит отдать пользователю кода, который создаёт объекты так что в таких случаях можно, например, назвать функцию CreateConcatenatedString, по названию вполне понятно, что строка была создана, а значит, вызывающий код ответственен за её удаление чтобы выделить память заранее, пришлось бы вынести часть логики, специфичной для функции сложения (вычисление длины) наружу, а это тоже не очень хорошо в большинстве же случаев, конечно new и delete стоит оставить в специальных классах, которые контролируют время жизни объектов (в данном случае им вполне мог бы быть std::string, или что-то более общее типа boost::shared_array) |
| Автор: dumb 28.6.2009, 03:46 |
| и, как правило, к таким функциям добавляются DestroyConcatenatedString или DestroyString(если есть группа создающих функций), даже если их содержание = delete, так как вовсе не очевиден метод выделения памяти внутри создающей функции. |
| Автор: maxim1000 28.6.2009, 13:47 | ||
и то правда впрочем, не так уж и редко случается, что delete - единственный, используемый в программе, способ для удаления указателей хотя обёртка типа std::string естественно лучше |