คุณกำลังขาดการคัดลอกเครื่องมือก่อสร้างและย้ายสิ่งก่อสร้าง การดัดแปลงอย่างง่ายในโปรแกรมของคุณจะแสดงหลักฐานว่ามีการก่อสร้างเกิดขึ้นที่ใด
คัดลอกตัวสร้าง
#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
คัดลอกตัวสร้างและย้ายตัวสร้าง
หากคุณให้บริการย้าย ctor มันจะเป็นที่ต้องการอย่างน้อยหนึ่งสำเนาเหล่านั้น:
#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
เอกสารอ้างอิง
หากคุณต้องการหลีกเลี่ยงสำเนาเหล่านั้นคุณสามารถห่อ callable ของคุณใน wrapper อ้างอิง ( 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 มากเกินไปก็ไม่ได้ถูกเรียกเนื่องจาก wrapper อ้างอิงตอนนี้เป็นสิ่งที่ถูกคัดลอก / ย้าย ไม่ใช่สิ่งที่อ้างอิง นอกจากนี้วิธีการขั้นสุดท้ายนี้ให้สิ่งที่คุณกำลังมองหาอยู่ t.x
กลับมาอยู่ในมีที่ในความเป็นจริงการแก้ไขให้main
11
มันไม่ได้อยู่ในความพยายามก่อนหน้า ไม่สามารถความเครียดพอนี้อย่างไร: ต้องระวังการทำเช่นนี้ อายุการใช้งานวัตถุเป็นสำคัญ
ย้ายและไม่มีอะไรนอกจาก
ในที่สุดหากคุณไม่สนใจที่จะเก็บรักษา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()
{
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
ที่นี่คุณสามารถเห็นวัตถุที่ถูกสร้างขึ้นการอ้างอิง rvalue ไปที่กล่าวเดียวกันแล้วส่งตรงไปยังstd::thread::thread()
ที่ที่มันถูกย้ายอีกครั้งไปยังสถานที่พำนักสุดท้ายเป็นเจ้าของกระทู้จากจุดนั้นไปข้างหน้า ไม่มีตัวคัดลอกที่เกี่ยวข้อง dtors ที่เกิดขึ้นจริงนั้นขัดแย้งกับสองกระสุนและวัตถุคอนกรีตปลายทางสุดท้าย