Здравствуйте, Skorodum, Вы писали:
S>Это на коде адаптированном под версия <5.10 который вы привели выше?
S>Можете показать отладачную печать?
Код, которым тестировалось (константная ссылка). Для теста по значению поменять определения сигнала-слота в Bar.
| main.cpp |
| #include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QScopedPointer>
#include <QtCore/QThread>
#include <QtCore/QTimer>
#define PRINT_FUNCTION_INFO qDebug() << Q_FUNC_INFO << this << QThread::currentThread();
struct Foo {
Foo() { PRINT_FUNCTION_INFO }
Foo(const Foo&) { PRINT_FUNCTION_INFO }
Foo(Foo&&) { PRINT_FUNCTION_INFO }
Foo& operator=(const Foo&) { PRINT_FUNCTION_INFO return *this; }
Foo& operator=(Foo&&) { PRINT_FUNCTION_INFO return *this; }
~Foo() { PRINT_FUNCTION_INFO }
};
class Bar : public QObject {
Q_OBJECT
public:
explicit Bar(QObject* parent = nullptr) : QObject(parent) {}
void emitSignals() { emit dataByValueSignal(foos); }
QVector<Foo> foos;
signals:
void dataByValueSignal(const QVector<Foo>&) const;
public slots:
void dataByValue(const QVector<Foo>& foo)
{
qDebug() << QThread::currentThread() << Q_FUNC_INFO << foo.size();
// It is ok to pass "big" QVector object by value because of COW (but const reference is still better).
// Also can safely modify copy of 'COW class' transfered with signals and slots in another thread.
// Using non-const methods will make deep copy of QVector content behind the scene.
//foo.append(Foo()); // <- comment out to see effect of COW
foos = foo;
qDebug() << QThread::currentThread() << "consumer data" << QString::number( uint64_t(foos.constData()), 16 );
}
};
class Producer : public QObject
{
Q_OBJECT
const Bar& bar;
public:
Producer(const Bar& b): bar(b){}
public slots:
void do_produce() {
Bar anotherBar;
anotherBar.foos.append(Foo());
// connect to object in another thread and pass object with COW by value
// no copies of QVector *content* at this point and thread safe
qDebug() << QThread::currentThread() << "producer data before signal" << QString::number( uint64_t(anotherBar.foos.constData()), 16 );
QObject::connect(&anotherBar, &Bar::dataByValueSignal, &bar, &Bar::dataByValue);
anotherBar.emitSignals();
qDebug() << QThread::currentThread() << "producer data after signal" << QString::number( uint64_t(anotherBar.foos.constData()), 16 );
// can safely modify local copy of Qt class
QThread::sleep(1);
anotherBar.foos.pop_front();
qDebug() << QThread::currentThread() << anotherBar.foos.size();
}
};
int main(int argc, char *argv[])
{
// main thread
const Bar bar;
qRegisterMetaType<QVector<Foo>>("QVector<Foo>");
const QScopedPointer<QThread> thread(new QThread);
Producer prod(bar);
prod.moveToThread(thread.data());
const QCoreApplication a(argc, argv);
QObject::connect(thread.data(), &QThread::started, &prod, &Producer::do_produce);
QObject::connect(thread.data(), &QThread::finished, qApp, &QCoreApplication::quit);
QTimer::singleShot(0, qApp, [&thread]{thread->start();}); // start thread when event loop is running
return qApp->exec();
}
#include "main.moc"
|
| |
Выхлоп release, по значению
Foo::Foo() 0x7f7633163c98 QThread(0x563e12505fe0)
Foo::Foo(Foo&&) 0x7f762c005c58 QThread(0x563e12505fe0)
Foo::~Foo() 0x7f7633163c98 QThread(0x563e12505fe0)
QThread(0x563e12505fe0) producer data before signal "
7f762c005c58"
QThread(0x563e12505fe0) producer data after signal "
7f762c005c58"
QThread(0x563e12505e20) void Bar::dataByValue(QVector<Foo>) 1
QThread(0x563e12505e20) consumer data "
7f762c005c58"
Foo::Foo(const Foo&) 0x7f762c0054d8 QThread(0x563e12505fe0)
Foo::~Foo() 0x7f762c0054d8 QThread(0x563e12505fe0)
QThread(0x563e12505fe0) 0
Выхлоп release, по константной ссылке
Foo::Foo() 0x7f4b1df57c98 QThread(0x5610c684dfe0)
Foo::Foo(Foo&&) 0x7f4b18005c58 QThread(0x5610c684dfe0)
Foo::~Foo() 0x7f4b1df57c98 QThread(0x5610c684dfe0)
QThread(0x5610c684dfe0) producer data before signal "
7f4b18005c58"
QThread(0x5610c684dfe0) producer data after signal "
7f4b18005c58"
QThread(0x5610c684de20) void Bar::dataByValue(const QVector<Foo>&) 1
QThread(0x5610c684de20) consumer data "
7f4b18005c58"
Foo::Foo(const Foo&) 0x7f4b180054d8 QThread(0x5610c684dfe0)
Foo::~Foo() 0x7f4b180054d8 QThread(0x5610c684dfe0)
QThread(0x5610c684dfe0) 0