Russian Qt Forum
Ноябрь 24, 2024, 02:18 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3 4   Вниз
  Печать  
Автор Тема: qDeleteAll - глупый и опасный метод!  (Прочитано 41942 раз)
frostyland
Гость
« Ответ #15 : Январь 26, 2011, 15:10 »

Код
C++ (Qt)
struct MyData {
...
~MyData( void )  {}
 
int mType;
QString * mText;
...
};
 
void Data2Storage( QList<MyData> & src, QVector <QString *> & textStorage )
{
qDeleteAll(textStorage);
size_t i, limit = src.size();
textStorage.resize(limit);
for (i = 0; i < limit; ++i)
 textStorage[i] = src[i].mText;
}
 

В данном примере Вы не играетесь с невалидными указателями. Вы их тут же перезаписываете валидными.
Проблема данного Вашего кода в том, что Вы можете уверенно манипулировать данными только в данной видимости. В паре шагов от qDeleteAll...
То есть, сделав qDeleteAll(desperateContainer), мы получаем НЕПУСТОЙ контейнер со списком опасных хвостов - указателей на освобожденную память.
Не дай бог нам куда-нибудь его передать случайно за границы метода. Потому что там мы потеряем информацию, что память почищена, а хвосты остались!
Страшный и непредсказуемый desperateContainer, чей размер больше 0, но в нем полно бомб... о которых нам уже никто не подскажет...
Попробуй мы по нему итерировать desperateContainer.count(), foreach, или любые алгоритмы, меняющие данные - и нам пипец.

Почему я и говорю, что это слупый и опасный метод, уточню - при работе с контейнерами )))
Записан
BRE
Гость
« Ответ #16 : Январь 26, 2011, 15:19 »

Почему я и говорю, что это слупый и опасный метод, уточню - при работе с контейнерами )))
Ну так и пользуйся этой функцией с осторожностью.  Подмигивающий
... также как и оператором delete, он тоже очень опасен тем, что не зануляет указатель на только что освобожденную память.
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #17 : Январь 26, 2011, 16:36 »

> Там ни слова про контейнеры, верно?

Неверно.

Цитировать
Notice that qDeleteAll() doesn't remove the items from the container; it merely calls delete on them. In the example above, we call clear() on the container to remove the items.
This function can also be used to delete items stored in associative containers, such as QMap and QHash. Only the objects stored in each container will be deleted by this function; objects used as keys will not be deleted.

Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
frostyland
Гость
« Ответ #18 : Январь 27, 2011, 08:02 »

Скажите, а почему Вас совершенно не волнуют соображения эффективности? Хотели ли мы освободить память занимаемую указателями? Не всегда, как показывает пример. Зачем тогда столько эмоций?  Улыбающийся
2 момента.
1. Эффективность. Сомнительно. Сабж делетит память по указателям вызовом delete, это зачастую гораздо более затратно (ведь там скорее всего не new int хранились, а объекты каких-то реальных классов), нежели делетить потом сами указатели методом clear.
2. Безопасность. Еще раз скажу, см. мой пост выше. За пределами вызова qDeletaAll остается контейнер с неопределенным поведением, то есть, вдумайтесь! мы смотрим на непустой контейнер, и уже не знаем, а валиден ли он? А вдруг где-то в каком-то методе кто-то применил к нему qDeletaAll??? Это же невозможно узнать, не перелопатив вручную весь код (а если в поставке бинарники, то вообще невозможно).
Поэтому пользоваться этим глупым и опасным методом можно только так, как указано выше, то есть непосредственно в одном методе и только одному разработчику, который все знает про собственный стиль программирования )))

ЗЫ. ИМХО, эффективность в ущерб безопасности - это моветон. И, вообще смешно говорить об какой-то серьезной угрозе эффективности:
Код
C++ (Qt)
template <typename T>
Q_OUTOFLINE_TEMPLATE void QList<T>::clear()
{
   *this = QList<T>();
}
 
Скорее всего, просто недодумали ребята.
« Последнее редактирование: Январь 27, 2011, 08:22 от frostyland » Записан
asvil
Гость
« Ответ #19 : Январь 27, 2011, 10:53 »

frostyland, наверно Вам просто стоит рассмотреть erlang или scheme, как вариант решения проблемы побочных эфектов.
Вы абсолютно верно замечаете факт наличия опасности в виде контейнера с невалидными указателями, но поймите кто-то программирует функции без уже упомянутых побочных эфектов и не может согласиться с Вашими доводами.
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #20 : Январь 27, 2011, 17:47 »

frostyland, Ну тогда получается, что оператор delete тоже глупый и опасный.

Как уже было сказано выше, никто не мешает имплементировать qClearAll с нужным функционалом.
« Последнее редактирование: Январь 27, 2011, 17:49 от pastor » Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Kolobok
Гость
« Ответ #21 : Январь 27, 2011, 18:05 »

frostyland, а как ты будешь QMap и QHash обрабатывать, если ключи тоже указатели и еще будут использоваться?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #22 : Январь 27, 2011, 18:15 »

frostyland, а как ты будешь QMap и QHash обрабатывать, если ключи тоже указатели и еще будут использоваться?
Ключ-указатель смысла не имеет т.к операторы  == и < не дадут разумного результата. А с мыслью согласен - ситуаций когда что-то остается невалидным после вызова метода или ф-ции сколько угодно
Записан
rp80
Гость
« Ответ #23 : Июнь 04, 2012, 18:07 »

Например с временными объектами.
Код:
for (int i = 0; i < topLevelItemCount(); ++i)
{
    qDeleteAll(topLevelItem(i)->takeChildren());
}

Здесь нет смысла чистить контейнер, так как он тут же удаляется.
Записан
DmitryM
Гость
« Ответ #24 : Июнь 04, 2012, 18:44 »

Вот те пример:
Код
C++ (Qt)
class CTest
{
public:
 ~CTest()
 {
   qDebug()<<"die";
 }
};
//....
CTest* _array[] = {new CTest(),new CTest(),new CTest(),new CTest(),new CTest()};
qDeleteAll(_array, _array + COUNT(_array));
 
О том что контейнер не может поддерживать удаление элемента, ты не подумал?
Записан
DmitryM
Гость
« Ответ #25 : Июнь 04, 2012, 21:25 »

Зачем нужен метод, чистящий память, но оставляющий в контейнере невалидные указатели?
Это абсолютно глупо! Нет ни одного случая, где бы эти указатели-хвосты могли бы понадобиться.
.clear() просто должно было быть там по умолчанию в реализации qDeleteAll.
Все равно приходится либо помнить об его вызове, либо писать свою над-функцию...
Совершенно непонятна такая стратегия  Непонимающий
qDeleteAll это алгоритм, а не метод!
Идите туда где вы учились и пусть там вам объяснят разницу между обобщенным программированием и объектно-ориентированным программированием.
Записан
frostyland
Гость
« Ответ #26 : Июнь 05, 2012, 11:25 »

qDeleteAll это алгоритм, а не метод!
Идите туда где вы учились и пусть там вам объяснят разницу между обобщенным программированием и объектно-ориентированным программированием.
Вы, уважаемый хам, сейчас написали ерунду. qDeleteAll - это метод (function), что следует как из понятия "функция", так и из документации Qt на qDeleteAll (почитайте, это несложно, правда, по-английски).
И зачем Вы здесь приплели обобщенное программирование, мне тоже не понятно. Это никак не относится к вопросу. Умничаете?
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #27 : Июнь 05, 2012, 11:50 »

Цитировать
In the C++ programming language, algorithms are components that perform algorithmic operations on containers and other sequences. The C++ standard provides some standard algorithms collected in the <algorithm> standard header.

From Qt Reference Documentation:
Цитировать
Qt provides a number of global template functions in <QtAlgorithms> that work on containers and perform well-know algorithms.
qDeleteAll относится к этим функциям.


http://en.wikipedia.org/wiki/Method_(computer_programming)
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #28 : Июнь 05, 2012, 11:55 »

Если добросовестно изучать то всегда найдутся вещи которые, на наш взгляд, неудачны. Напр мне QPoint::x() кажется полной глупостью. Но я не навязываю своего мнения и не пытаюсь доказать типа "я грамотный и умный, а ты темный дурак"  Улыбающийся
Записан
Akon
Гость
« Ответ #29 : Июнь 05, 2012, 12:34 »

qDeleteAll находит свое применение в типичных отношениях Parent - Children с двунаправленными связями. Т.е. мы можем делать delete child, и деструктор child удаляет свой указатель из контейнера, инкапсулированного в parent  (и делает другие побочные эффекты). Parent в деструкторе хачит детей с помощью qDeleteAll(), ничего больше не надо, контейнер при этом чистится автоматом.

Мне лень смотреть, но наверняка qDeleteAll используется в деструкторе QObject, поскольку там имеено такое отношение Parent - Children.
Записан
Страниц: 1 [2] 3 4   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.125 секунд. Запросов: 23.