Kopya yapımı ve taşıma yapımında eksik araç var. Programınızda yapılacak basit bir değişiklik, inşaatların yapıldığı yerdeki kanıtları sağlayacaktır.
Kopya Oluşturucu
#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;
}
Çıktı (adresler değişir)
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
Kopya Oluşturucu ve Taşı Oluşturucu
Bir taşıma kasası sağlarsanız, aksi takdirde bu kopyalardan en az biri için tercih edilir:
#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;
}
Çıktı (adresler değişir)
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
Referans Sarılmış
Bu kopyalardan kaçınmak isterseniz, çağrılabilirinizi bir referans sarmalayıcıya ( std::ref
) sarabilirsiniz . t
İplik geçirme kısmı yapıldıktan sonra kullanmak istediğiniz için durumunuz için bu geçerlidir. Pratikte , çağrı nesnelerine yapılan referanslara karşı iplik geçirirken çok dikkatli olmalısınız, çünkü nesnenin ömrü en az referansı kullanan iş parçacığı kadar uzamalıdır.
#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;
}
Çıktı (adresler değişir)
Constructed : 0x104057020
Thread is joining...
Thread running at : 11
x : 11
Destroyed : 0x104057020
Ben kopya-ctor ve move-ctor aşırı yükleri tutmak rağmen, ne de, çağrı sarıcı şimdi kopya / taşınan şey olduğu için çağrıldı; referans verdiği şey değil. Ayrıca, bu son yaklaşım muhtemelen aradığınızı sağlar; t.x
geri main
, aslında, değiştirilmiş 11
. Önceki denemelerde değildi. Ancak bunu yeterince vurgulayamıyorum: bunu yaparken dikkatli olun . Nesne ömrü kritiktir .
Hareket Et, Ve Hiçbir Şey Ama
Son olarak, t
örneğinizde olduğu gibi tutmaya ilgi duymuyorsanız , örneği yol boyunca hareket ederek doğrudan iş parçacığına göndermek için taşıma semantiğini kullanabilirsiniz.
#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;
}
Çıktı (adresler değişir)
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
Burada nesnenin yaratıldığını, söz konusu aynı değere ilişkin rvalue referansının daha sonra doğrudan gönderildiği std::thread::thread()
ve o noktadan itibaren iş parçacığının sahip olduğu nihai dinlenme yerine tekrar taşındığı görebilirsiniz. Hiçbir kopyalayıcı dahil değildir. Gerçek dtorlar iki mermiye ve nihai hedef beton nesnesine karşıdır.