Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> +Выделение и освобождение памяти на разных уровнях, нормально ли так поступать? 
V
    Опции темы
zim22
Дата 27.6.2009, 14:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 29
Всего: 69



Выполняю задание из Страуструпа.
Цитата

Напишите функцию cat, принимающую в качестве аргументов две C-строки, которая возвращает строку, являющуюся их конкатенацией. Воспользуйтесь оператором new для выделения памяти под результат.


Функцию я написал:
Код

const char *cat(const char *lhs, const char *rhs) {
  char *ret = new char[strlen(lhs) + strlen(rhs) + 1];
  strcpy(ret, lhs);
  strcat(ret, rhs);
  return ret;
}

Проблема в том, что однажды кто-то мне сказал, что память должна выделяться и освобождаться на одном уровне. 
скорей всего для того, чтобы пользователю не пришлось вручную удалять строку - т.к. он может забыть это сделать.
Код

const char *str = cat("first_", "second");
delete [] str;

как тогда переписать функцию, чтобы удовлетворялось требование "уровня"? есть ли такое требование вообще? smile

Это сообщение отредактировал(а) zim22 - 27.6.2009, 14:17


--------------------
PM MAIL   Вверх
zkv
Дата 27.6.2009, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Участник Клуба
Сообщений: 2133
Регистрация: 23.7.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 92



zim22, безусловно, так писать нельзя. А если копнуть глубже, то new вообще пользоваться не стоит. 

Полагаю, учебная задача? Так сделайте то, что вас просят, для себя главное отложите, что это неправильно.
Можно подготовить два варианта: правильный и соответствующий заданию, при сдаче пояснить. 
Наверное так бы и поступил.

PS Радует то, что такой вопрос родился, многие бы просто прошли мимо, сделав то, что их просят.
PM MAIL   Вверх
zim22
Дата 27.6.2009, 14:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 29
Всего: 69



Цитата(zkv @  27.6.2009,  14:32 Найти цитируемый пост)
Полагаю, учебная задача? 

нет. задача не учебная. мне "для себя" необходимо понять, в чём ошибка "проектирования" метода и как её избежать.



--------------------
PM MAIL   Вверх
Andrew121
Дата 27.6.2009, 14:54 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 86
Регистрация: 21.6.2009

Репутация: 1
Всего: 1



Я в таких случаях предварительно выделяю память, и передаю указатель.
PM MAIL   Вверх
zkv
Дата 27.6.2009, 15:00 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Участник Клуба
Сообщений: 2133
Регистрация: 23.7.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 92



zim22, вы сами ответили на свой вопрос, есть необходимость использования new - используйте в там, где можно использовать и delete.
В данном случае, память следует выделять за пределами функции cat, там же ее (память) и освобождать.
Ну а если С++, то юзать чего нить типа boost::shared_ptr (который вроде ныне известен как std::tr1::shared_ptr).
Хотя если совсем C++, то тут и подобной задачи не возникнет: есть сущность - реализуй ее классом.
PM MAIL   Вверх
zim22
Дата 27.6.2009, 15:13 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 29
Всего: 69



Цитата(Andrew121 @  27.6.2009,  14:54 Найти цитируемый пост)
Я в таких случаях предварительно выделяю память, и передаю указатель.

думаю, пока остановлюсь на этом же варианте.
Код

void cat(char *buffer, const char *lhs, const char *rhs) {  
  strcpy(buffer, lhs);
  strcat(buffer, rhs);
}

char *s1 = "first_";
char *s2 = "second";

char *buf = new char[strlen(s1) + strlen(s2) + 1];
cat(buf, s1, s2);
delete [] buf;



--------------------
PM MAIL   Вверх
maxim1000
Дата 27.6.2009, 17:23 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 1
Всего: 110



есть очень простой принцип, которому стоит следовать в большинстве (если не во всех) случаев: ответ на вопрос о владении объектом должен быть очевиден, всё остальное - способы достижения этой очевидности
(под владением подразумевается, кто должен удалить этот объект)
а способы такие:
1. стековые объекты
2. boost::shared_ptr, boost::scoped_ptr, std::auto_ptr
3. близость создания и удаления в коде
4. документация (имена функций, переменных, комментарии)
(попробовал упорядочить по "степени надёжности", но это может быть субъективно)

в некоторых случаях последний способ не так уж и страшен
например, паттерн "фабрика" часто как раз и предполагает наличие метода, который создаёт объект, но удалением занимается кто-то другой (возможно, даже не метод этой фабрики)

использовать умные указатели на этом уровне не всегда хорошо, т.к. каждый тип умного указателя навязывает свою стратегию владения, а иногда это решение стоит отдать пользователю кода, который создаёт объекты

так что в таких случаях можно, например, назвать функцию CreateConcatenatedString, по названию вполне понятно, что строка была создана, а значит, вызывающий код ответственен за её удаление

чтобы выделить память заранее, пришлось бы вынести часть логики, специфичной для функции сложения (вычисление длины) наружу, а это тоже не очень хорошо

в большинстве же случаев, конечно new и delete стоит оставить в специальных классах, которые контролируют время жизни объектов (в данном случае им вполне мог бы быть std::string, или что-то более общее типа boost::shared_array)

Это сообщение отредактировал(а) maxim1000 - 27.6.2009, 17:25


--------------------
qqq
PM WWW   Вверх
dumb
Дата 28.6.2009, 03:46 (ссылка) |    (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 3
Всего: 158



Цитата(maxim1000 @  27.6.2009,  18:23 Найти цитируемый пост)
в таких случаях можно, например, назвать функцию CreateConcatenatedString
и, как правило, к таким функциям добавляются DestroyConcatenatedString или DestroyString(если есть группа создающих функций), даже если их содержание = delete, так как вовсе не очевиден метод выделения памяти внутри создающей функции.
PM MAIL   Вверх
maxim1000
Дата 28.6.2009, 13:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 1
Всего: 110



Цитата(dumb @  28.6.2009,  03:46 Найти цитируемый пост)
и, как правило, к таким функциям добавляются DestroyConcatenatedString или DestroyString(если есть группа создающих функций), даже если их содержание = delete, так как вовсе не очевиден метод выделения памяти внутри создающей функции. 

и то правда
впрочем, не так уж и редко случается, что delete - единственный, используемый в программе, способ для удаления указателей

хотя обёртка типа std::string естественно лучше



--------------------
qqq
PM WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0564 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.