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

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

Страниц: 1 2 [3]   Вниз
  Печать  
Автор Тема: Передача по ссылке или указателю?  (Прочитано 21003 раз)
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #30 : Август 18, 2011, 10:33 »

Механизм интересный, полностью скрывает себя от программиста.
Ну как полностью... Возможность «выстрелить себе в ногу» есть всегда: http://www.prog.org.ru/topic_19004_0.html Было бы желание.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #31 : Август 18, 2011, 19:44 »

Да, копирование произойдёт не в том участке кода, что иногда может быть критичным, но это уже довольно частный случай.
Вы меня прекрасно понимаете  Улыбающийся
Получая структуру по значению мы не имеем средств проконтролировать происходит ли копирование или нет - ведь механизм полностью скрыт. Смириться с возможным копированием (мол, да это довольно частный случай) - это прекрасно для студентов (и их преподавателей), никто не будет требовать от лабы "производительности". Но уже на 100К данных (примерно) такое приложение перестает работать

Вообще мне кажется все было не так. Собрались креативные пацаны (тогда они еще не были зажравшимися "троллями") и загорелись интересной идеей типа "вот каждый грамотный знает что гонять воздух по значению плохо - а мы докажем что нет!". Ну и вполне доказали. Но это всего лишь один из возможных подходов/идей, со своими плюсами-минусами (на мой взгляд минусы весомее). А сейчас идея (которая когда-то была творческой) вдалбливается механически и без всякого осмысления - становится грустно  Плачущий

 
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #32 : Август 18, 2011, 19:53 »

Возможность «выстрелить себе в ногу» есть всегда: http://www.prog.org.ru/topic_19004_0.html Было бы желание.
Вы уже третий раз об этом упоминаете Улыбающийся А ведь стрелять себе в ногу весьма полезно - значит чему-то научился. Одно дело прочитать о "корове" - мне все было понятно, и совсем другое - столкнуться с ней на практике. "Много знать" и "уметь сделать" - очень разные вещи  Улыбающийся
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #33 : Август 18, 2011, 21:04 »

Вы уже третий раз об этом упоминаете Улыбающийся А ведь стрелять себе в ногу весьма полезно - значит чему-то научился.
Ну посмотреть, как это делают другие тоже иногда полезно.

Не по теме топика, конечно, но расскажу, как недавно подстрелил ногу:
Код
C++ (Qt)
class ThreadBase : protected QThread
{
   Q_OBJECT
public:
   explicit ThreadBase( QObject* = 0 );
   bool isInitialized();
   void launch();
   ~ThreadBase();
 
protected:
   virtual bool initialize();
   virtual void run();
   virtual void execute() = 0;
   virtual void finalize();
   bool initialized;
   bool finish;
};
Код
C++ (Qt)
ThreadBase :: ThreadBase( QObject* parent ) :
   QThread( parent )
{
   initialized = false;
   finish = false;
}
 
ThreadBase :: ~ThreadBase()
{
   finish = true;
   quit();
   while ( isRunning() )
   {
       yieldCurrentThread();
   }
}
 
bool ThreadBase :: isInitialized()
{
   return initialized;
}
 
bool ThreadBase :: initialize()
{
   return true;
}
 
void ThreadBase :: run()
{
   initialized = initialize();
   if ( initialized )
   {
       while( !finish )
       {
           execute();
           usleep( 1 );
       }
   }
   else
   {
       finish = true;
   }
   finalize();
}
 
void ThreadBase :: finalize()
{
}
Дальше я наследую от этого класса и переопределяю initialize, execute и finalize. И вроде бы всё работает, но потом я понимаю, что не всё работает так, как задумывалось.
А теперь вопрос: что было не так и где же я ошибся?

Ответ: Не выполнялась финализация, в итоге и память текла и, что намного хуже, не сохранялись некоторые настройки, не передавались результаты и т.п.
Если унаследованный класс потока удаляется, когда он ещё не вышел из run(), то по выходе из цикла while вызовется finalize() самого ThreadBase, а вовсе не унаследованного класса. Мы все, конечно, знаем, что виртуальные функции из деструктора вызывать нельзя, но то, что в вызванной намного раньше деструктора может вызваться не перегруженная версия функции finalize из-за того, что в v-table уж стёрты данные об унаследованном классе, я не подумал.


Вообще мне кажется все было не так. Собрались креативные пацаны (тогда они еще не были зажравшимися "троллями") и загорелись интересной идеей типа "вот каждый грамотный знает что гонять воздух по значению плохо - а мы докажем что нет!".
Я всё же останусь при мнении, что это было сделано именно для передачи параметров в сигналах/слотах.
« Последнее редактирование: Август 18, 2011, 21:10 от LisandreL » Записан
brankovic
Гость
« Ответ #34 : Август 18, 2011, 21:54 »

Если унаследованный класс потока удаляется, когда он ещё не вышел из run(),

А при чём тут виртуальные функции, разве можно вообще пользоваться объектом после удаления? (если наследник удаляется, то база тоже, т.е. сам QThread тоже уже удалён?)
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #35 : Август 18, 2011, 22:10 »

А при чём тут виртуальные функции, разве можно вообще пользоваться объектом после удаления? (если наследник удаляется, то база тоже, т.е. сам QThread тоже уже удалён?)
Мы говорим про момент, когда мы находимся в деструкторе ~ThreadBase(). ~QThread() ещё не вызывался, так что к полям этих двух классов можно обращаться, к полям дочернего класса - нет.
P.S. В данном классе всё могло бы сработать - в финализации были только закрытие БД и запись в лог, но в общем случае делать финализацию после того, как первый деструктор отработает действительно дурацкий, так как в общем случае поля объекта могут понадобиться.
« Последнее редактирование: Август 18, 2011, 23:03 от LisandreL » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #36 : Август 19, 2011, 02:41 »

Не вижу прямой ошибки но дызайн мне не нравится
Код
C++ (Qt)
ThreadBase :: ~ThreadBase()
{
   finish = true;
   quit();
   while ( isRunning() )
   {
       yieldCurrentThread();
   }
}
Деструктор вызовется уже когда нитка завершилась, поэтому quit() и isRunning бесполезны. Если же это задумывалось для "delete this" (из нитки) то while никогда не кончится, да и в любом случае удалять нельзя пока нитка не завершена

Отот finish я бы просто застрелил, ничего хорошего он не делает.
Код
C++ (Qt)
       while (execute())
           usleep( 1 );    // а вместо этого лучше виртуальчик
 

Записан
brankovic
Гость
« Ответ #37 : Август 19, 2011, 11:27 »

Мы говорим про момент, когда мы находимся в деструкторе ~ThreadBase ()

понял, ~ThreadBase как бы поджидает на выходе, поэтому поля finish и прочие ещё не разрушились Улыбающийся

Edit: хотя нет, не понятно. Пусть есть тред 1 (главный) и тред 2 (в его контексте выполняется ThreadDerived). Кто вызвал деструктор ThreadDerived? Если тред 1, то он завис на время выполнения деструктора. Если тред 2, то он был в execute и вообще зависнет. Можете пояснить всё-таки кто вызвал деструктор треда?
« Последнее редактирование: Август 19, 2011, 11:43 от brankovic » Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #38 : Август 19, 2011, 14:19 »

Если тред 1, то он завис на время выполнения деструктора. Если тред 2, то он был в execute и вообще зависнет.
Родительский поток. Да зависнет. Эти потоки существуют в течении всего жизненного цикла программы и уничтожаются при её завершении. Так что ничего особо плохого в этом зависании нет.
Записан
Страниц: 1 2 [3]   Вверх
  Печать  
 
Перейти в:  


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