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

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

Страниц: [1] 2 3   Вниз
  Печать  
Автор Тема: QList + qSort  (Прочитано 24809 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Сентябрь 25, 2009, 15:12 »

Добрый день

Код:
#include <qDebug>

#define  NUM_TEST 1024

struct CTest {
CTest( double x ) : mX(x) {}
   ~CTest( void ) { qDebug() << "destruct " << mX; }

bool operator < ( const CTest & t ) const { return mX < t.mX; }

// data
double mX;
QString mDummy;
};

int main(int argc, char *argv[])
{
(void) argc;
(void) argv;
QList <CTest> theList;

for (int i = 0; i < NUM_TEST; ++i)
theList.append(CTest(double(qrand()) / RAND_MAX));

qSort(theList.begin(), theList.end());

return 0;
}
Консоль печатает вызовы ~CTest.
Вопрос: почему и хорошо/правильно ли это для QList? Ведь QList хранит указатели на данные и было бы очень к месту сортировать указатели не вызывая тонны конструкторов/деструкторов.
Записан
BlackTass
Гость
« Ответ #1 : Сентябрь 25, 2009, 15:14 »

как мне кажется вызовы деструктора идут после ретурна, то есть когда удаляются локальные переменные. Попробуйте поставить куДебаг перед ретурном и посмотреть до или после будут вызовы деструкторов
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Сентябрь 25, 2009, 15:26 »

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

Код:
#include <qDebug>

#define  NUM_TEST  8

struct CTest {
     CTest( double x ) : mX(x) {}
   ~CTest( void ) { qDebug() << "destruct " << mX; }

     bool operator < ( const CTest & t ) const { return mX < t.mX; }
     
// data
     double mX;
     QString mDummy;
};

int main(int argc, char *argv[])
{
(void) argc;
(void) argv;
QList <CTest> theList;
qDebug() << "\nAppending";

for (int i = 0; i < NUM_TEST; ++i)
theList.append(CTest(double(qrand()) / RAND_MAX));

qDebug() << "\nSorting";

qSort(theList.begin(), theList.end());
// qSort(theList);
qDebug() << "\nEnd";

return 0;
}

Консоль
Цитировать
Appending
destruct  7.82637e-06
destruct  0.131538
destruct  0.755605
destruct  0.45865
destruct  0.532767
destruct  0.218959
destruct  0.0470446
destruct  0.678865

Sorting
destruct  0.532767
destruct  0.755605
destruct  0.678865
destruct  0.532767
destruct  0.0470446
destruct  0.0470446
destruct  0.131538
destruct  0.218959
destruct  0.678865

End
destruct  0.755605
destruct  0.678865
destruct  0.532767
destruct  0.45865
destruct  0.218959
destruct  0.131538
destruct  0.0470446
destruct  7.82637e-06
Записан
Winstrol
Гость
« Ответ #3 : Сентябрь 25, 2009, 15:36 »

Вопрос: почему и хорошо/правильно ли это для QList? Ведь QList хранит указатели на данные и было бы очень к месту сортировать указатели не вызывая тонны конструкторов/деструкторов.
Видимо, потому, что qSort ничего не известно о внутренностях QList.
Записан
BRE
Гость
« Ответ #4 : Сентябрь 25, 2009, 15:52 »

qSort во всю использует qSwap, который создает временный объект T. Вот для разрушения временных объектов и вызывается деструктор.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Сентябрь 25, 2009, 15:56 »

Видимо, потому, что qSort ничего не известно о внутренностях QList.
Тогда уж надо предоставить пользователю метод QList::sort и написать в букваре что он может быть значительно быстрее чем qSort. А пока я вижу что

QList <MyObject *> может быть во много раз быстрее (для хороших объектов) чем QList <MyObject>
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Сентябрь 25, 2009, 16:09 »

qSort во всю использует qSwap, который создает временный объект T. Вот для разрушения временных объектов и вызывается деструктор.
То да, но для QList это сделано не по уму. Если уж мы тратим драгоценные 4/8 байт для указателя на объект - чего мы тогда сам объект дергаем/перемещаем?
Записан
BRE
Гость
« Ответ #7 : Сентябрь 25, 2009, 16:30 »

То да, но для QList это сделано не по уму. Если уж мы тратим драгоценные 4/8 байт для указателя на объект - чего мы тогда сам объект дергаем/перемещаем?
Как писал выше Winstrol, qSort (как и qSwap и другие алгоритмы) сделан универсальным, ему не важен тип контейнер, он не знает его внутреннее устройство.
На счет функций sort оптимизированных для каждого контейнера.... По моему, для написания GUI qSort работает достаточно быстро, а большего Qt и не должна предоставлять. IMHO, не нужно от нее требовать всего.  Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Сентябрь 25, 2009, 17:18 »

Да как будто аккуратная сортировка есть "слишком много чтобы просить" Улыбающийся
Заметим, кстати, что QList::swap имеется и переставляет указатели, а не объекты.
Записан
ритт
Гость
« Ответ #9 : Сентябрь 28, 2009, 11:13 »

хрен пойму почему в данном случае не использовать QList <CTest*> ?

а что при "Appending" вызывается полный набор деструкторов, это нормально, да?Улыбающийся
Записан
shadone
Гость
« Ответ #10 : Сентябрь 28, 2009, 11:40 »

хороший вопрос и отличная возможность показать себя и вписать свое имя в историю - ждем патчей реализующий специализацию template<typename Container> void qSort(Container &container) для QList. Кто возьмется?
Записан
shadone
Гость
« Ответ #11 : Сентябрь 28, 2009, 11:43 »

хрен пойму почему в данном случае не использовать QList <CTest*> ?

а что при "Appending" вызывается полный набор деструкторов, это нормально, да?Улыбающийся
кстати хороший вопрос откуда они берутся. Скорее всего из-за создание временного объекта на стеке и в релизной сборке этих деструкторов вероятно не будет...
Записан
BRE
Гость
« Ответ #12 : Сентябрь 28, 2009, 12:08 »

кстати хороший вопрос откуда они берутся. Скорее всего из-за создание временного объекта на стеке и в релизной сборке этих деструкторов вероятно не будет...
Как это не будет - будет.
Вот здесь создается временный объект:
Код
C++ (Qt)
               theList.append( CTest(double(qrand()) / RAND_MAX));
 
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Сентябрь 28, 2009, 12:12 »

хрен пойму почему в данном случае не использовать QList <CTest*> ?
Потому что qSort требует оператор < а для <CTest*> он будет сравнивать указатели - т.е. делать совсем не то что нужно
а что при "Appending" вызывается полный набор деструкторов, это нормально, да?Улыбающийся
Это "неизбежное зло" любого контейнера - данные должны быть сначала скопированы "в нутро".
Правда здесь с ихним "shallow copy" это не так болезненно как в STL.

Цитировать
кстати хороший вопрос откуда они берутся. Скорее всего из-за создание временного объекта на стеке и в релизной сборке этих деструкторов вероятно не будет...
будет, деструктор для временного CTest должен вызываться по окончании theList.append
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #14 : Сентябрь 28, 2009, 12:21 »

хороший вопрос и отличная возможность показать себя и вписать свое имя в историю - ждем патчей реализующий специализацию template<typename Container> void qSort(Container &container) для QList. Кто возьмется?
Никто кроме Qt, потому что все глухо "private" (обратная сторона медали). Этот feature request я им уже написал
Записан
Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


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