【发布时间】:2017-10-02 08:10:23
【问题描述】:
好的,我有这样的事情:
void EmailReceiverThread::foreachEmailAccount(ConfigEmailAccount account)
{
Email email;
EmailReader emailReader(account);
while (emailReader.pollEmail(email))
{
writeEmailToDatabase(email);
}
}
ForeachEmailAccount 是 EmailReceiverThread 中的一个槽。它是从 run() 方法调用的:
GetConfigEmailDAO* accountReader = new GetConfigEmailDAO(type, m_channel);
connect(accountReader, SIGNAL(emailAccount(ConfigEmailAccount)),
this, SLOT(foreachEmailAccount(ConfigEmailAccount)), Qt::QueuedConnection);
DbThread::postAction(accountReader);
GetConfigEmailDAO 进行查询,获取电子邮件帐户并发出:
emit emailAccount(account);
到目前为止,这有效。问题是,我正在复制类 ConfigEmailAccount。我想避免那种性能冲击。所以,我的想法是使用 c++11 移动语义发出帐户:
emit emailAccount(std::move(account));
我用新语法重写了槽和信号:
void foreachEmailAccount(ConfigEmailAccount&& account);
不幸的是,这不起作用。我有下一个编译错误:
moc_emailreceiverthread.cpp:88: error: cannot bind ‘ConfigEmailAccount’ lvalue to ‘ConfigEmailAccount&&’
case 1: _t->foreachEmailAccount((*reinterpret_cast< ConfigEmailAccount(*)>(_a[1]))); break;
我能做什么?
此处是可验证的最小示例:
#include <QCoreApplication>
#include <QObject>
class ConfigEmailAccount
{
QString some_data;
};
class GetConfigEmailDAO : public QObject
{
Q_OBJECT
public:
void execute();
signals:
void emailAccount(ConfigEmailAccount&& account);
};
void GetConfigEmailDAO::execute()
{
ConfigEmailAccount account;
emit emailAccount(std::move(account));
}
class EmailReceiverThread : public QObject
{
Q_OBJECT
public:
void execute();
public slots:
void foreachEmailAccount(ConfigEmailAccount&& account);
};
void EmailReceiverThread::execute()
{
GetConfigEmailDAO* accountReader = new GetConfigEmailDAO;
connect(accountReader, SIGNAL(emailAccount(ConfigEmailAccount)),
this, SLOT(foreachEmailAccount(ConfigEmailAccount)), Qt::QueuedConnection);
accountReader->execute();
}
void EmailReceiverThread::foreachEmailAccount(ConfigEmailAccount&& account)
{
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qRegisterMetaType<ConfigEmailAccount>("ConfigEmailAccount");
EmailReceiverThread reader;
reader.execute();
return a.exec();
}
#include "main.moc"
【问题讨论】:
-
我敢打赌,Qt 的信号和插槽中没有对移动语义和右值引用的特殊支持,因为它们是在 C++11 之前的版本中设计的。因此,您最好使用 Qt 的本机解决方案来避免大量复制:或者重新设计
ConfigEmailAccount类以使用 implicit sharing,或者,如果很难或不可能,则使用QSharedPointer<ConfigEmailAccount>作为信号和插槽。 -
你可以简单地通过指针传递你的对象。
-
为什么不把它包装成
std::shared_ptr<ConfigEmailAccount>并传递呢? -
如果将多个插槽连接到同一个信号会发生什么?
标签: c++ qt c++11 move qt-signals