The following snippet runs fine:
#include <memory>
#include <cassert>
int main()
{
auto ptr1 = std::make_shared<int>(10);
assert(ptr1.use_count() == 1);
auto ptr2 = std::move(ptr1);
assert(ptr1 == nullptr);
auto ptr3 = static_cast<std::shared_ptr<int>&&>(ptr2);
assert(ptr2 == nullptr);
assert(ptr3.use_count() == 1);
}
It looks std::move
does several operations, one of them is reseting the moved shared pointer somehow, so is this thread safe? For instance if i have something like:
void ThreadLogic()
{
if (sharedPtr != nullptr)
{
DoSomething(std::move(sharedPtr));
}
else
{
DoSomethingElse();
}
}
Is that std::move(sharedPtr)
atomic or should I protect the check (the critical section) there by some other means?
You have a misconception about what std::move
does. In fact std::move
does nothing. It's just a compile time mechanism with the meaning: I no longer need this named value.
This then causes the compiler to use the value in different ways, like call a move constructor/assignment instead of copy constructor/assignment. But the std::move
itself generates no code so nothing to be affected by threads.
The real question you should be asking is whether the move constructor of shared_ptr
is thread safe and the answer is: No.
But the point of the shared_ptr
is not to share the shared_ptr
but to share what it points too. Do not pass a shared_ptr
by reference to threads, instead pass it by value so each thread gets it own shared_ptr
. Then it is free to move that around at will without problems.
The shared_ptr
protects the lifetime of the thing it points to. The reference count the shared_ptr
uses is thread safe but nothing else. It only manages the lifetime of the pointed to objects in a thread safe way so it doesn't get destroyed as long as any shared_ptr
has hold of the object.