您缺少检测复制构造和移动构造。对您的程序进行简单的修改,即可提供正在构建的证据。
复制构造函数
#include <iostream>
#include <thread>
#include <functional>
using namespace std;
class tFunc{
int x;
public:
tFunc(){
cout<<"Constructed : "<<this<<endl;
x = 1;
}
tFunc(tFunc const& obj) : x(obj.x)
{
cout<<"Copy constructed : "<<this<< " (source=" << &obj << ')' << endl;
}
~tFunc(){
cout<<"Destroyed : "<<this<<endl;
}
void operator()(){
x += 10;
cout<<"Thread running at : "<<x<<endl;
}
int getX() const { return x; }
};
int main()
{
tFunc t;
thread t1{t};
if(t1.joinable())
{
cout<<"Thread is joining..."<<endl;
t1.join();
}
cout<<"x : "<<t.getX()<<endl;
return 0;
}
输出(地址不同)
Constructed : 0x104055020
Copy constructed : 0x104055160 (source=0x104055020)
Copy constructed : 0x602000008a38 (source=0x104055160)
Destroyed : 0x104055160
Thread running at : 11
Destroyed : 0x602000008a38
Thread is joining...
x : 1
Destroyed : 0x104055020
复制构造函数和移动构造函数
如果您提供搬家公司,则至少应优先选择以下一种副本:
#include <iostream>
#include <thread>
#include <functional>
using namespace std;
class tFunc{
int x;
public:
tFunc(){
cout<<"Constructed : "<<this<<endl;
x = 1;
}
tFunc(tFunc const& obj) : x(obj.x)
{
cout<<"Copy constructed : "<<this<< " (source=" << &obj << ')' << endl;
}
tFunc(tFunc&& obj) : x(obj.x)
{
cout<<"Move constructed : "<<this<< " (source=" << &obj << ')' << endl;
obj.x = 0;
}
~tFunc(){
cout<<"Destroyed : "<<this<<endl;
}
void operator()(){
x += 10;
cout<<"Thread running at : "<<x<<endl;
}
int getX() const { return x; }
};
int main()
{
tFunc t;
thread t1{t};
if(t1.joinable())
{
cout<<"Thread is joining..."<<endl;
t1.join();
}
cout<<"x : "<<t.getX()<<endl;
return 0;
}
输出(地址不同)
Constructed : 0x104057020
Copy constructed : 0x104057160 (source=0x104057020)
Move constructed : 0x602000008a38 (source=0x104057160)
Destroyed : 0x104057160
Thread running at : 11
Destroyed : 0x602000008a38
Thread is joining...
x : 1
Destroyed : 0x104057020
参考包装
如果要避免这些副本,可以将可调用对象包装在参考包装中(std::ref
)。由于您想t
在穿线部分完成后加以利用,因此这对于您的情况是可行的。实际上,在针对调用对象的引用进行线程化时,必须非常小心,因为对象的生存期必须至少与使用引用的线程一样长。
#include <iostream>
#include <thread>
#include <functional>
using namespace std;
class tFunc{
int x;
public:
tFunc(){
cout<<"Constructed : "<<this<<endl;
x = 1;
}
tFunc(tFunc const& obj) : x(obj.x)
{
cout<<"Copy constructed : "<<this<< " (source=" << &obj << ')' << endl;
}
tFunc(tFunc&& obj) : x(obj.x)
{
cout<<"Move constructed : "<<this<< " (source=" << &obj << ')' << endl;
obj.x = 0;
}
~tFunc(){
cout<<"Destroyed : "<<this<<endl;
}
void operator()(){
x += 10;
cout<<"Thread running at : "<<x<<endl;
}
int getX() const { return x; }
};
int main()
{
tFunc t;
thread t1{std::ref(t)}; // LOOK HERE
if(t1.joinable())
{
cout<<"Thread is joining..."<<endl;
t1.join();
}
cout<<"x : "<<t.getX()<<endl;
return 0;
}
输出(地址不同)
Constructed : 0x104057020
Thread is joining...
Thread running at : 11
x : 11
Destroyed : 0x104057020
请注意,尽管我保留了copy-ctor和move-ctor重载,但都没有被调用,因为现在引用包装器就是要被复制/移动的东西。不是它引用的东西。同样,这种最终方法可以满足您的需求。实际上,将t.x
back in main
修改为11
。以前没有尝试过。但是,不能对此施加足够的压力:请谨慎执行此操作。对象生存期至关重要。
移动,什么也没有
最后,如果您对t
示例中的保留不感兴趣,则可以使用move语义将实例直接发送到线程,并沿过程移动。
#include <iostream>
#include <thread>
#include <functional>
using namespace std;
class tFunc{
int x;
public:
tFunc(){
cout<<"Constructed : "<<this<<endl;
x = 1;
}
tFunc(tFunc const& obj) : x(obj.x)
{
cout<<"Copy constructed : "<<this<< " (source=" << &obj << ')' << endl;
}
tFunc(tFunc&& obj) : x(obj.x)
{
cout<<"Move constructed : "<<this<< " (source=" << &obj << ')' << endl;
obj.x = 0;
}
~tFunc(){
cout<<"Destroyed : "<<this<<endl;
}
void operator()(){
x += 10;
cout<<"Thread running at : "<<x<<endl;
}
int getX() const { return x; }
};
int main()
{
thread t1{tFunc()}; // LOOK HERE
if(t1.joinable())
{
cout<<"Thread is joining..."<<endl;
t1.join();
}
return 0;
}
输出(地址不同)
Constructed : 0x104055040
Move constructed : 0x104055160 (source=0x104055040)
Move constructed : 0x602000008a38 (source=0x104055160)
Destroyed : 0x104055160
Destroyed : 0x104055040
Thread is joining...
Thread running at : 11
Destroyed : 0x602000008a38
在这里,您可以看到该对象已创建,将对same的右值引用直接发送到std::thread::thread()
,在该对象处再次将其移动到最终的静止位置,该位置从该线程开始一直归线程所有。不涉及复制指针。实际的干向是抵靠两个壳和最终目标混凝土对象。