LINUX.ORG.RU

[Qt] ThreadTimer пример из М.Шлее; не понимаю как живет локальная переменная


0

0

Вот пример от Макса Шлее:

/* ======================================================================
**  main.cpp
** ======================================================================
**
** ======================================================================
**  Copyright (c) 2007 by Max Schlee
** ======================================================================
*/

#include <QtGui>

// ======================================================================
class MyThread : public QThread {
Q_OBJECT
private:
    int m_nValue;

public:
    MyThread() : m_nValue(10)
    {
    }

    void run()
    {
        QTimer timer;
        //^^^^^^^^^^^
        //а где будет эта переменная когда run() закончится
        //а event loop будет продолжаться и тред должен будет
        //дрыгать этим таймером раз в секунду?

        connect(&timer, SIGNAL(timeout()), SLOT(slotNextValue()));
        timer.start(1000);

        exec();
    }

signals:
    void finished    (   );
    void currentValue(int);

public slots:
    void slotNextValue()
    {
        emit currentValue(--m_nValue);

        if (!m_nValue) {
            emit finished();
        }
        
    }
};

// ----------------------------------------------------------------------
int main(int argc, char** argv)
{
    QApplication app(argc, argv);
    QLCDNumber   lcd;
    MyThread     thread;

    QObject::connect(&thread, SIGNAL(currentValue(int)), 
                     &lcd,    SLOT(display(int))
                    );
    QObject::connect(&thread, SIGNAL(finished()), 
                     &app,    SLOT(quit())
                    );

    lcd.setSegmentStyle(QLCDNumber::Filled);
    lcd.display(10);
    lcd.resize(220, 90);
    lcd.show();
    thread.start();
 
    return app.exec();
}

#include "main.moc"

Вопрос в коментарии в функции run().

Прочитал у тогоже Шлее что в Qt

в основном передаются ссылки на объекты, а не копии объектов,

и что не надо объявлять статические объекты а надо new и давать им parent чтоб Qt с ними сам разобрался

не недо delete'ать объекты

что Qt ведет счет ссылкам на объект и убьет объект когда ссылки кончатся

Все эти умные(возможно мной не понятые) слова как бы говорят: «Не парься, делай как в примерах, память не потечет и ссылок в никуда не будет».

Но я старый Cшник, и хочу понять где будет жить локальная переменная

QTimer timer;

объявленная в функции run(), когда run() отработает а тред еще бежит.

Предположу что

когда run() отработает


уже не будет

тред еще бежит.


C qt не знаком.

anon_666 ()
Ответ на: комментарий от alex_custov

>По поводу памяти - http://silmor.de/33

Просмотрел, не уверен что понял, но слов 'heap' и 'stack' там точно нет. Там рассказано как Qt следит шоб объекты не болтались в памяти когда ими не пользуются. Как это работает на объектах выделенных в куче легко представить. А что будет когда объект живет в стеке представить трудо. Стек вещь железная, связанная с архитектурой процессора. Функция кончилась, стек будет отмотан к состоянию до вызова функции. Куда денется локальный объект на который Instance Counting говорит что он еще нужен?

Умный Qt скопирует объект? Куда?

imatveev13 ()
Ответ на: комментарий от imatveev13

А, еще вариант, заметив что локальный объект пользуется за пределами функции Qt может создать объект сразу в куче, а в функции подсунуть ссылку.

imatveev13 ()
Ответ на: комментарий от imatveev13

man разделяемые объекты. То что ты на стеке создаешь объект во все не значит, что он целиком создается там, посмотри в сторону QSharedData, явного и неявного разделения.

Gorthauer ★★★★★ ()
Ответ на: комментарий от Gorthauer

Вот для примера.

class Foo
{
//Foo
private:
  FooPrivate *p;
}
Берем и создаем где-нить
{
Foo f;
}
а теперь подумай, что будет в FooPrivate, когда область видимости у Foo кончится?

Gorthauer ★★★★★ ()

> QLCDNumber

Вам точно нужен Qt3, а не Qt4?

По теме: exec() и есть цикл событий, run() не закончится, пока этот цикл событий жив.

Dendy ★★★★★ ()

> Но я старый Cшник, и хочу понять где будет жить локальная переменная QTimer timer;объявленная в функции run(), когда run() отработает а тред еще бежит.

Когда run() отработает, будет вызван деструктор ~QTimer, далее ~QObject в котором сигналы будут отключены.

QObject::~QObject () [virtual]

Destroys the object, deleting all its child objects.

All signals to and from the object are automatically disconnected, and any pending posted events for the object are removed from the event queue. However, it is often safer to use deleteLater() rather than deleting a QObject subclass directly.

MKuznetsov ★★★★★ ()
Ответ на: комментарий от Gorthauer

посмотри в сторону QSharedData

Смотрю http://doc.qt.nokia.com/4.6/qshareddata.html

совсем кратко, не поясняет ничего. А Inherited by QAbstractXmlNodeModel вообще смущает. Похоже QSharedData не то место откуда ноги растут.

Еще там есть http://doc.qt.nokia.com/4.6/implicit-sharing.html#implicitly-shared

Уже теплее:

Implicit sharing automatically detaches the object from a shared block if the object is about to change and the reference count is greater than one. (This is often called copy-on-write or value semantics.)

Если выход из функции при reference count is greater than one канает под copy-on-write это объясняет.

То что ты на стеке создаешь объект во все не значит, что он целиком создается там

Не понял, объект что может существовать частично?

imatveev13 ()
Ответ на: комментарий от Gorthauer

А какая связь между областью видимости(живет в компиляторе) и стеком(живет в контексте процесса и в регистре процессора)?

imatveev13 ()
Ответ на: комментарий от imatveev13

>>Куда денется локальный объект на который Instance Counting говорит что он еще нужен?

Instance Counting считает не объекты, а указатели на внутренние данные (http://doc.trolltech.com/4.4/shared.html#implicit-sharing), которые создаются в куче. Локальный объект при выходе из функции/блока/и т.д. удалится в любом случае. Внутренние данные удалятся только если ими больше никто не пользуется.

alex_custov ★★★★★ ()
Ответ на: комментарий от Dendy

Вам точно нужен Qt3, а не Qt4?

Такая книжка подвернулась. А там есть в тредах разница?

По теме: exec() и есть цикл событий, run() не закончится, пока этот цикл событий жив.

О! Вот это точно объясняет. Ура! Цикл событий не есть отдельная форма существования треда, все происходит в run() по любому -> цикл событий не нужен(вреден) если внутри треда нет объектов события от которых должен обрабатывать тред.

imatveev13 ()
Ответ на: комментарий от Dendy

По теме: exec() и есть цикл событий, run() не закончится, пока этот цикл событий жив.

И локальная переменная будет жива т.к. цикл обработки событий живет в run(). И никаких мрачных тайн, о которых невнятно бормочут цитаторы док про хитрые ссылки на хитрые объекты.

imatveev13 ()
Ответ на: комментарий от imatveev13

>И никаких мрачных тайн, о которых невнятно бормочут цитаторы док про хитрые ссылки на хитрые объекты.

ключевая подсказка - exec()

http://doc.trolltech.com/4.6/qthread.html#exec


...


alex_custov (11.08.2010 0:19:58)



Второй пост, кстати.

anon_666 ()
Ответ на: комментарий от alex_custov

Именно так я себе и представлял и жизнь объектов в куче и стеке. Неясность с примером возникла из за того что плохо прочитал это:

int QThread::exec () [protected] Enters the event loop and waits until exit() is called, returning the value that was passed to exit(). The value returned is 0 if exit() is called via quit().

Надо было понять что enters значит туды заходит и там крутится, и пока крутится, exec () не вернется.

imatveev13 ()
Ответ на: комментарий от Gorthauer

а теперь подумай, что будет в FooPrivate, когда область видимости у Foo кончится?

если деструктор правильно написал - всё почистится, если нет - утечка памяти будет :)

специально такие штуки делать - это я не знаю... гораздо безопаснее лицо в вентилятор совать :)

shty ★★★★★ ()
Ответ на: комментарий от shty

если деструктор правильно написал - всё почистится, если нет - утечка памяти будет :)

специально такие штуки делать - это я не знаю... гораздо безопаснее лицо в вентилятор совать :)

Ну так это пример, специально там юзается безопасный указатель, и приват удаляется только если им никто уже не пользуется

Gorthauer ★★★★★ ()
Ответ на: комментарий от Gorthauer

Ну так это пример, специально там юзается безопасный указатель, и приват удаляется только если им никто уже не пользуется

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

shty ★★★★★ ()
Ответ на: комментарий от shty

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

Определяешь указатель как QSharedDataPointer и делаешь у класса конструктор копирования, который как раз передает в новый объект указатель на него.

Gorthauer ★★★★★ ()
Ответ на: комментарий от Gorthauer

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

Определяешь указатель как QSharedDataPointer и делаешь у класса конструктор копирования, который как раз передает в новый объект указатель на него.

а зачем вообще такое делать, какой use case?

shty ★★★★★ ()
Ответ на: комментарий от shty

>>а зачем вообще такое делать, какой use case?

Экономия ресурсов по принципу copy-on-write. Ничего там скольского нет, это есть и работает много где.

alex_custov ★★★★★ ()
Ответ на: комментарий от Gorthauer

>и приват удаляется только если им никто уже не пользуется
да, но только чтобы это можно было понять, нужен пример куда более объёмный, чем ваш :)

xydo ★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.