сигнал и параметр Qt объекта стека в качестве ссылки

Могу ли я иметь "висящую ссылку" со следующим кодом (в конечном слоте, подключенном к myQtSignal)?

class Test : public QObject
{
    Q_OBJECT

signals:
    void myQtSignal(const FooObject& obj);

public:
    void sendSignal(const FooObject& fooStackObject)
    {
        emit  myQtSignal(fooStackObject);
    }
};

void f()
{
    FooObject fooStackObject;
    Test t;
    t.sendSignal(fooStackObject);
}

int main()
{
    f();
    std::cin.ignore();
    return 0;
}

В частности, если emit и slot не выполняются в тот же поток.

25
задан Guillaume07 2 January 2018 в 17:07
поделиться

2 ответа

Если область действия, в которой существует объект, заканчивается и затем используется, он будет ссылаться на уничтоженный объект, что приведет к неопределенному поведению. Если вы не уверены, закончится ли область действия, лучше всего выделить объект в бесплатном хранилище через new и использовать что-то вроде shared_ptr для управления его временем жизни.

0
ответ дан 28 November 2019 в 18:11
поделиться

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

Qt :: DirectionConnection

В целом мы можем принять, что это не будет проблемой для прямых соединений, так как эти слоты вызываются немедленно. Ваш сигнал излучается до тех пор, пока не будут вызваны все слоты. Как только это произойдет, emit myQtSignal(fooStackObject); вернется, как обычная функция. На самом деле, myQtSignal(fooStackObject); является регулярной функцией! Ключевое слово emit полностью для вашей выгоды - оно ничего не делает. Сигнальная функция просто особенная, потому что ее код генерируется компилятором Qt: moc .

Qt :: QueuedConnection

Бенджамин Т указал в документации, что аргументы копируются, но я думаю, что полезно изучить, как это работает под капотом (по крайней мере, в Qt 4).

Если мы начнем с компиляции нашего проекта и поиска нашего сгенерированного moc-файла, мы можем найти что-то вроде этого:

// SIGNAL 0
void Test::myQtSignal(const FooObject & _t1)
{
    void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
    QMetaObject::activate(this, &staticMetaObject, 0, _a);
}

Итак, в принципе, мы передаем QMetaObject::activate несколько вещей: QObject, metaObject для нашего типа QObject, нашего идентификатора сигнала и указатель на каждый из аргументов, которые получил наш сигнал.

Если мы исследуем QMetaObject::activate , мы обнаружим, что он объявлен в qobject.cpp . Это неотъемлемая часть работы QObjects. После просмотра некоторых вещей, которые не имеют отношения к этому вопросу, мы находим поведение для подключений в очереди. На этот раз мы вызываем QMetaObject::queued_activate с нашим QObject, индексом сигнала, объектом, представляющим соединение от сигнала к слоту, и снова аргументами.

if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread)
    || (c->connectionType == Qt::QueuedConnection)) {
    queued_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv);
    continue;

Достигнув queued_activate, мы наконец-то добрались до сути вопроса.

Во-первых, он формирует список типов соединений из сигнала:

QMetaMethod m = sender->metaObject()->method(signal);
int *tmp = queuedConnectionTypes(m.parameterTypes());

Важным в queuedConnectionTypes является то, что он использует QMetaType::type(const char* typeName) для получения идентификатора метатипа типа аргумента из сигнатуры сигнала. , Это означает две вещи:

  1. Тип должен иметь идентификатор QMetaType, поэтому он должен быть зарегистрирован в qRegisterMetaType .

  2. Типы нормализованы . Это означает "const T & amp;" и "T" отображается на идентификатор QMetaType для T.

Наконец, queued_activate передает типы аргументов сигнала и заданные аргументы сигнала в QMetaType::construct для копирования-создания новых объектов со временами жизни, которые будут длиться до тех пор, пока слот не будет вызван в другом потоке. Как только событие было поставлено в очередь, сигнал возвращается.

И это в основном история.

15
ответ дан 28 November 2019 в 18:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: