c++ - Using what happens to raw pointers when their shared_ptr dies

问题描述:

I am working on a game engine that utilizes actors made up of various components. These actors own their components and the components own their parent actor as well. I have a member function called Destroy that breaks the circular reference chain so that everything can be cleaned up. I am trying to do basically everything as components. For example, even cameras are components attached to certain actors. This means that things such as the renderer need access to the camera components in order to extract their view and proj matrices so I want to keep a list in the renderer of the currently active cameras and the windows in which they render to. I can't make it shared pointer because that would prevent actors from being destroyed when they are supposed to. I don't wanna use a weak pointer either because it will need to be locked every frame in order to get the view and projection matrices. So I was going to try and use a raw pointer and just check it for nullptr before using it. Unfortunately that doesn't work. When the shared_ptr to the camera component goes outta scope the raw pointer stays valid but just points to garbage? I was under the impression that the shared_ptr should have cleaned it up. Would this be a case where I would need a custom deleter? One that deletes and sets the value to nullptr?

网友答案:

When the shared_ptr to the camera component goes outta scope the raw pointer stays valid but just points to garbage?

Then it's not "valid"; it's dangling.

I was under the impression that the shared_ptr should have cleaned it up. Would this be a case where I would need a custom deleter? One that deletes and sets the value to nullptr?

Were you expecting a std::shared_ptr pointing to an object obj to magically set all raw pointers throughout your program with the value &obj to nullptr? That is impossible!

It is your responsibility to NULL out pointers that would otherwise dangle. By using raw pointers at the same time as smart pointers, you promised yourself that you knew what you were doing and would keep the raw pointers safe, but then failed to do so.

If you want "raw pointers" that do not increment the reference count, but which are pointing to an otherwise smartly-managed object, then use std::weak_ptrs.

If you cannot use weak pointers for whatever reason then, yes, you will have to NULL out your raw pointers yourself. A custom deleter would be a good way to go about this, indeed.