Qt использует boost :: shared_ptr в сигнале / слоте - PullRequest
8 голосов
/ 26 января 2011

Возможно ли это, и если да, то как я могу создать сигнал / слот в Qt, который является константной ссылкой на shared_ptr? Я хочу сигнал, который выглядит следующим образом:

void signal( shared_ptr<SomeClass> const & )

Я знаю, как это сделать без постоянной ссылки, это просто тип shared_ptr<SomeClass>, но из соображений эффективности * я бы хотел избежать копирования. Тот же синтаксис для ссылочного типа не работает:

Q_DECLARE_METATYPE(shared_ptr<SomeClass> const &)
qRegisterMetaType<shared_ptr<SomeClass> const&>();

Многие из стандартных API имеют QString const &, поэтому я предполагаю, что это принципиально возможно, и я просто не могу понять синтаксис.


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

Ответы [ 3 ]

7 голосов
/ 26 января 2011

Пока я обнаружил, что могу просто сделать это:

Q_DECLARE_METATYPE(shared_ptr<SomeClass>)
qRegisterMetaType<shared_ptr<SomeClass> >();
qRegisterMetaType<shared_ptr<SomeClass> >("std::shared_ptr<SomeClass>const&");

Я пытаюсь проверить, действительно ли это работает правильно. Документация здесь не ясно, что на самом деле происходит. Похоже, что ссылочный тип const в сигнале / слоте будет просто маршалироваться как нормальный shared_ptr<SomeClass>, что здесь вполне нормально. Однако было бы неплохо иметь какую-то гарантию, что это должно работать как таковое.

У меня такое ощущение, что простая shared_ptr<SomeClass> версия - это все, что нужно, и это пространство имен boost, которое мешает сигналам. Вторая версия появляется только для регистрации сигнала в глобальном пространстве имен для более легкого использования.


Из тестирования я могу подтвердить, что часть const &, как упоминалось, полностью игнорируется в соединениях с очередями. Каждый подключенный слот получает новую копию объекта. Это очень неудачно. (

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

Таким образом, хотя каждый connect в конечном итоге будет копировать данные для соединения в очереди, ссылки все равно немного помогают. А также, если у вас есть несколько сигналов, отправленных локально (тот же поток), вы можете избежать еще большего копирования.

2 голосов
/ 26 января 2011

Согласно одному из ответов на этот вопрос Тип аргумента для сигнала Qt и слота, имеет ли значение постоянный эталонный квалификатор? , для соединения в очереди объект копируется независимо от того, как вы подключаете сигнал и слот.

Поскольку вы используете несколько потоков, соединение ставится в очередь. Если вы боитесь стоимости мьютекса, попробуйте использовать SomeClass * напрямую.

0 голосов
/ 22 сентября 2015

Для полноты картины, я полагаю, следует упомянуть, что Qt имеет собственную реализацию общего указателя, QSharedPointer , которая ведет себя точно так же, как std :: shared_ptr.В конце концов, вам все равно придется зарегистрировать тип аргумента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...