Is the following considered a bad/good practice? Why?
class Scene
{
public:
std::weak_ptr<Node> AddChild(std::unique_ptr<Node> node);
std::unique_ptr<Node> DetachChild(std::string name);
private:
std::vector<std::shared_ptr<Node>> mNodes;
};
The idea is to make sure that Scene
is the only owner of its children, and force to transfer ownership when adding a Node
to that scene. However there should be a way for clients to have access to Nodes stored inside the Scene (without constantly looking up it by name/id).
Typical example would be something like:
Alternative would be also to add using unique_ptr
but return raw pointer
, however the text could be updated in different classes and there should always be a check that the label exists (e.g. there can be a running Tween
function that updates text in a loop which you trigger in "Fire and forget" mode and just want to make sure it won't access dangling pointer(think of cocos2d
actions) Even if checking just means just catching and assert).
What you want is not possible due to the nature of shared_ptr
. While unique_ptr
allows you to extract the pointer without deleting it, shared_ptr
does not.
What you want is also not good practice, due to threading. Even if you implement your own smart pointer that does exactly what you want, how do you use it? It would be possible for a user to lock one of those handles, then in another thread you convert your internal smart pointer to a unique_ptr
. How does that work? What you have is two pieces of code both conceptually owning the object, but only one of them controls its lifetime.
Unless you forbid threading, that is very much in Murphy's realm.
Things like this are precisely why shared_ptr
cannot abandon its ownership of the pointer.
Basically I need
unique_ptr
that can return a pointer that will become null as soon as the originalunique_ptr
gets destroyed.
This is precisely why weak_ptr
does not provide direct access to the internal pointer. You have to lock it, which guarantees that you can access the memory for as long as you keep that shared_ptr
around.
This coding pattern prevents the exact kind of data races that your idea will create.
shared_ptr
was designed by some very smart people working over a long period of time. Ignore its wisdom at your own peril.