为什么线程对类变量的更改没有影响?

时间:2018-06-27 19:41:32

标签: c++ multithreading c++11

#include <iostream>
#include <thread>

using namespace std;

struct A{

 void Add(){
    ++val;
 } 

 int val = 0;
};

int main(){
   A a;
   thread t(&A::Add,a);
   t.join();

   std::cout << a.val << std::endl;
}

为什么最终将+1添加到值的线程的执行没有效果? std :: cout仅为零。我原本期望1。

2 个答案:

答案 0 :(得分:6)

您正在按值传递a,因此线程获得了自己的私有副本,该私有副本与a中的main不同-线程然后修改副本,并在线程死亡时进行修改该对象随它死亡,并且找不到更改。 a中的main从未修改,因此保留其原始值。如果要从线程内更改a中的main,则需要传递引用或指针。

如果要从多个线程访问变量,您可能还想阅读同步原子

答案 1 :(得分:1)

正如@JesperJuhl所说,您传递的是a的副本,因此main的变量永远不会被修改,但是除此之外,引用不能传递给其他线程。线程的参数总是按值传递,因此,您需要传递一个指针或一个reference_wrapper,该指针或指针可以传递一个引用,但包装在一个可复制的对象中:

#include <iostream>
#include <thread>

using namespace std;

struct A{

 void Add(){
    ++val;
 } 

 int val = 0;
};

int main(){
   A a;

   // Passing a reference_wrapper is the standard way.

   // Passing a pointer would imply to change your method signature
   // and implementation if it were a free function instead of a 
   // class member function.
   // In your specific case it is irrelevant though.
   thread t(&A::Add,std::ref(a));
   // or thread t(&A::Add,&a);

   t.join();

   std::cout << a.val << std::endl;
}