#include <iostream>
#include <memory>
#include <vector>
#include <thread>
using namespace std;
class MyClass{
public:
MyClass(){
cout << "Created " << this << " at " << std::this_thread::get_id() << endl;
}
void SayHi(){
cout << "Say hi from thread " << std::this_thread::get_id() << endl;
}
virtual ~MyClass(){
cout << "Destroyed " << this << " at " << std::this_thread::get_id() << endl;
}
};
void Use(std::unique_ptr<MyClass> m){
m->SayHi();
}
int main(){
auto m = std::unique_ptr<MyClass>(new MyClass());
cout << std::boolalpha;
// Prints true
cout << "is null " << static_cast<bool>(m) << endl;
m->SayHi();
std::thread t1(Use, std::move(m));
// Prints false
cout << "is null " << static_cast<bool>(m) << endl;
// WTF? this works?!?!?
m->SayHi();
// Thank you C++ designers that I at least check...
if(m)
m->SayHi();
}
t1.join();
}
Почему unique_ptr остается юзабельным после std::move? Это считается хорошим дизайном? Кому нужен такой сценарий?
Я бы вот хотел чтобы в том вызове оно или не скомпилировалось или упало в рантайме чтобы рано найти ошибку. А так при передаче указателя в другой поток никакой речи о thread safety быть не может. Можно возразить что unique_ptr не должен решать эту проблему. Но это еще вопрос, а почему это не должен?