一 、概述
QtConcurrent提供一组并发执行的函数,能够快速、方便的实现多线程运行。其中QtConcurrent::run函数能够方便的将耗时比较长的函数、成员函数转移到其他线程去执行。在使用QtConcurrent::run的过程用,当run函数将成员函数转移到其他线程运行时,发现并不能改变成员变量的值。
二、问题
先看代码
class ChangeValue
{
public:
ChangeValue();
void Change() { value = 55; }
int GetValue() { return value; }
private:
int value = 0;
};
ChangeValue类有一个Change的成员函数,该函数用来改变私有成员value的值。现在我把Change成员函数想象成是一个非常耗时的操作,我要把它移动到其他线程中,防止主线程被卡死。代码如下:
void MainWindow::on_pushButton_clicked()
{
ChangeValue change_value;
auto future = QtConcurrent::run(change_value, &ChangeValue::Change);
future.waitForFinished();
qDebug() << change_value.GetValue();
}
通过运行QtConcurrent::run函数,实现将Change成员函数移动到其他线程运行。但是结果却不符合预期。通过qDebug输出发现value的值并没有改变。为什么会这样?
通过分析发现,之所以会这样。是因为QtConcurrent::run函数会将ChangeValue对象整个拷贝到新线程中运行,默认的拷贝构造函数,是值拷贝。类似与参数传递。ChangeValue只会更改拷贝之后的value值。所以函数执行完之后,拷贝之前的value值是不会变得。
下面修改代码验证一下
class ChangeValue
{
public:
ChangeValue() : value(new int(0)) {};
void Change() { *value = 55; }
int GetValue() { return *value; }
private:
int *value = nullptr;
};
将value的修改为指针之后,再次运行。结果符合预期,value的值被成功修改为55。