Вам не вистачає приладобудування копіювання та переміщення конструкції. Проста модифікація вашої програми надасть докази того, що саме там відбуваються спорудження.
Конструктор копіювання
#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
Довідка загорнута
Якщо ви хочете уникнути цих копій, ви можете загортати свій дзвінок у обгортку посилання ( 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
По 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()
, де він знову переміщується до остаточного місця спокою, що належить потоку з цієї точки вперед. Жодних копій-копій не задіяно. Фактичні двигуни проти двох снарядів та конкретного об'єкта призначення.