Qt signal и slots: копируются ли ссылочные аргументы?

В платформе qt в большинстве библиотечных сигналов и слотов в качестве параметров используются указатели. Мне было интересно, если я создам «структуру» сигнального слота, которая принимает ссылку в качестве параметра вместо указателя, будет ли скопирован весь параметр или только 4 байта (32-битная система), как в обычной ссылке на С ++?

Я спрашиваю об этом, потому что кое-что заметил, когда создаю методы сигнала / слота с параметром ссылки. Когда я затем connect их, механизм автозаполнения в QTCreator не подсказывает мне ссылочные параметры, как он сделал бы с параметрами указателя. Он мне подсказывает штатным параметром. Например:

Создаю сигнал и слот:

...
signals:
     void mySignal(int& parameter);
private slots:
     void on_mySignal(int& parameter);

Затем я пытаюсь подключить их, и Qt не добавляет & для справки в параметр:

...
connect(this, SIGNAL(mySignal(int)), this, SLOT(on_mySignal(int)));

Мне нужно вручную изменить на:

connect(this, SIGNAL(mySignal(int&)), this, SLOT(on_mySignal(int&)));

Таким образом, мне интересно, работает ли ссылка даже с сигналом / слотом? Буду признателен за любую помощь.


person Łukasz Przeniosło    schedule 12.02.2017    source источник
comment
Ваша предпосылка ошибочна. Обычные ссылки C ++ не имеют размера, поскольку они не являются объектами. Вы не можете, например, использовать sizeof, чтобы получить размер ссылки. Также вам следует прекратить использовать устаревший синтаксис сигналов / слотов. Правильный синтаксис - connect(this, &Class::mySignal, this, &Class::on_mySignal);, поэтому вам не нужно об этом беспокоиться.   -  person nwp    schedule 12.02.2017
comment
Я понимаю, спасибо. Но чтобы ответить на главный вопрос: при использовании сигнала / слотов со ссылкой, копируется ли большой объем данных?   -  person Łukasz Przeniosło    schedule 12.02.2017
comment
Я ожидал бы копию int, даже если вы указали int &. Вы можете проверить это, присвоив аргументу в слоте, и посмотреть, изменился ли переданный вами параметр.   -  person nwp    schedule 12.02.2017
comment
int - это просто пример. В моем коде у меня есть большие контейнеры, переданные в аргументах как ссылки. Вот почему это меня беспокоит. Также большое спасибо за показ нового метода подключения сигнала / слота. Это действительно очень удобно.   -  person Łukasz Przeniosło    schedule 12.02.2017
comment
Обратите внимание, что контейнеры Qt, такие как QVector, используют копирование при записи, поэтому копирование QVectors не копирует данные. Если вы используете std::vectors, они фактически скопируют данные.   -  person nwp    schedule 12.02.2017
comment
Нет, большинство моих параметров в сигналах / слотах Qvector<something>&.   -  person Łukasz Przeniosło    schedule 12.02.2017


Ответы (1)


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

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

Если какая-либо из сторон передается по значению, QT копирует данные, чтобы не влиять на состояние базового объекта.

Для получения дополнительной информации см. в этом сообщении в блоге.

person Wolf    schedule 12.02.2017
comment
Йохан, вы не правы. Копирование не зависит от потоков, оно зависит от типа подключения слота. Даже в том же потоке аргументы ref копируются в случае подключения в очереди. Прочтите документацию Qt: doc.qt.io/qt-5/qt. html # ConnectionType-enum - person Dmitry Sazonov; 12.02.2017
comment
в документе говорится, что когда соединение ставится в очередь, аргумент копируется для сохранения в событии за сценой. Означает ли это, что движок проверяет, является ли аргумент ссылкой, и если да, то копирует значение? - person user2019716; 18.09.2019