QT:使用移动语义将信号连接到槽函数

4

好的,我有这样一个问题:

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 类来使用隐式共享,或者如果这很困难或不可能,可以在信号和槽中使用 QSharedPointer<ConfigEmailAccount> - Dmitry
你可以通过指针简单地传递你的对象。 - vahancho
1
为什么不将其包装为 std::shared_ptr<ConfigEmailAccount> 并传递它呢? - rustyx
2
如果将多个槽连接到同一个信号,会发生什么? - Velkan
1个回答

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接