Reputation: 18561
I´m starting playing around with std::unique_ptr
and I just don´t want to mess up things.
On my code, I´m creating a std::unique_ptr
, storing it on a vector
for later use in another context and continue using the pointer:
#include <iostream>
#include <string>
#include <memory>
#include <vector>
class MyClass {
public:
void doWhatever ()
{
std::cout << "Var = " << variable << std::endl;
}
int variable = 0;
};
class Controller {
public:
std::vector<std::unique_ptr<MyClass>> instances;
};
class OtherClass {
public:
void myFunction()
{
Controller control;
std::unique_ptr<MyClass> p(new MyClass);
control.instances.push_back(std::move(p));
// Continue using p.
p->doWhatever(); // Is this valid ?
p->variable = 10; // Is this valid ?
p->doWhatever(); // Is this valid ?
}
};
int main()
{
OtherClass cl;
cl.myFunction();
}
The code compiles, but I´m getting segmentation fault on execution.
I imagine that calls to p
after moving the pointer to the vector are invalid.... If so, what would be the solution here ? Moving to a shared_ptr ?
OBS: I cannot move to vector after using the pointer. In real application this will be running on a multi-threaded environment where one thead is using the vector data and the other continue using the original pointer p
.
Thanks for helping.
Upvotes: 0
Views: 6130
Reputation: 41220
In brief, no it is not valid to use any object after you've moved it. EDIT: Unless you are calling a function that has no preconditions (Thanks, Benjamin Lindley).
This is because when you std::move
a unique_ptr
, you are transferring ownership of that memory to another unique_ptr
. (What's really happening is that std::move
marks your unique_ptr
as an r-value reference, and then the constructor for the other unique_ptr
sees this and gleefully performs pointer stealing). The unique_ptr
that you've moved into can now do whatever it wants, including delete the memory and invalidate any other reference you have.
You can dereference the pointer into a raw pointer (via unique_ptr::get()
) to access what it's pointing at, and then move the unique pointer into the vector. However, the whole idea of a unique_ptr
is sole ownership; your raw pointer could at any time become invalid.
Upvotes: 0
Reputation: 2281
The name of unique pointer says it all. It is meant to be completely unique so when it goes out of scope it can be safely deleted.
When you use std::move
on the pointer, it casts it to a rvalue reference hat then invokes the move constructor, meaning it is moved, not copied. It is just like if you move a plate from the dishwasher to the cabinet, it isn't in the dishwasher. In code, that means that the unique_ptr
that is moved from is set to nullptr
Alternatives:
shared_ptr
. This will allow you to have multiple instances and after the last one is deleted the destructor will be called. Another plus of using this is that the vector could store weak_ptr
s if it shouldn't keep the object from being destroyed. std::move
on the unique_ptr
to move it into the vector
. This potentially unsafe because if you try to use that pointer after the vector is destroyed it is undefined behaviors because it would be a dangling reference. Upvotes: 3