Skip to main content
replaced http://gamedev.stackexchange.com/ with https://gamedev.stackexchange.com/
Source Link

I think you did a good job here and there's little to change. Now about the pointers and memory management...

I was told by an industry professional that smart pointers (like shared_ptr) are frowned upon in game engines

It is true. The game development industry is known for its fear of the Standard C++ Libraryfor its fear of the Standard C++ Library. From my own experience, for the most part it is just cargo cult from the early days of embedded development for Consoles that had very steep hardware limitations, and from when the Standard Library was still very new and not well implemented.

This is not to say that there aren't a few instances where this fear is justifiable, but in general I think it is very exaggerated. I suggest taking a look at this CppCon talk from last year's conference where some points about "C++ for game development" are discussed.


Now let's get to the point, when should you use a shared pointer, a unique pointer, a raw pointer or a reference?

  • shared_ptr is meant for when the lifetime of an object needs to be shared by distinct owners. The last owner holding a reference to the object will destroy it when it goes away. In your code specifically, who owns the Entities? If they are owned by the Scene, then you certainly don't need a shared pointer, because there's no shared ownership going on!

  • So how about unique_ptr? This one meant for when an object has a single owner during its lifetime. When the owner goes away, it deletes the object. Ownership can be transferred with std::move, but no two object can own the same unique_ptr. Should Scene be using unique_ptr? It could. Your vectors of entities could be storing then by unique_ptr. It would make your code a lot simpler by removing all manual cleanup that you are currently doing. It would also make sure your code never leaks memory in the event of an exception being thrown.

  • And raw pointers and references, where do they fit in this? At the compiler level, a reference and a pointer to an object are the same thing, but it makes a huge difference for the programmer. A pointer has the potential of being nullptr, you can assign null to it explicitly, so we use pointers when we know the object might be null and we are going to check for that. A reference, on the other hand, cannot have null assigned to it and cannot be rebound once initialized, so when we pass a parameter by reference, for instance, we are making it cristal clear to the reader that the object will not be null. NOTE that both a reference and a raw pointer convey no ownership semantics to the programmer whatsoever, so they should only be used for temporary references that no one will hold on to. If you need to pass or share ownership, that's when our friendly smart pointers come into play. In your code, you should now take this information into consideration and replace your raw pointers with references where a null is not expected and where you are not transferring or sharing ownership. One place where I'm pretty sure you've misused the shared pointer is in the render function:

void Render(std::shared_ptr<Core::Renderer> renderer, std::shared_ptr<Core::Window> window)

I see no reason for the Scene render to take shared ownership of those objects just for the drawing. Unless you have some serious threading going on, there's no way the objects can be destroyed while the scene is rendered. You should be using references in there.

I think you did a good job here and there's little to change. Now about the pointers and memory management...

I was told by an industry professional that smart pointers (like shared_ptr) are frowned upon in game engines

It is true. The game development industry is known for its fear of the Standard C++ Library. From my own experience, for the most part it is just cargo cult from the early days of embedded development for Consoles that had very steep hardware limitations, and from when the Standard Library was still very new and not well implemented.

This is not to say that there aren't a few instances where this fear is justifiable, but in general I think it is very exaggerated. I suggest taking a look at this CppCon talk from last year's conference where some points about "C++ for game development" are discussed.


Now let's get to the point, when should you use a shared pointer, a unique pointer, a raw pointer or a reference?

  • shared_ptr is meant for when the lifetime of an object needs to be shared by distinct owners. The last owner holding a reference to the object will destroy it when it goes away. In your code specifically, who owns the Entities? If they are owned by the Scene, then you certainly don't need a shared pointer, because there's no shared ownership going on!

  • So how about unique_ptr? This one meant for when an object has a single owner during its lifetime. When the owner goes away, it deletes the object. Ownership can be transferred with std::move, but no two object can own the same unique_ptr. Should Scene be using unique_ptr? It could. Your vectors of entities could be storing then by unique_ptr. It would make your code a lot simpler by removing all manual cleanup that you are currently doing. It would also make sure your code never leaks memory in the event of an exception being thrown.

  • And raw pointers and references, where do they fit in this? At the compiler level, a reference and a pointer to an object are the same thing, but it makes a huge difference for the programmer. A pointer has the potential of being nullptr, you can assign null to it explicitly, so we use pointers when we know the object might be null and we are going to check for that. A reference, on the other hand, cannot have null assigned to it and cannot be rebound once initialized, so when we pass a parameter by reference, for instance, we are making it cristal clear to the reader that the object will not be null. NOTE that both a reference and a raw pointer convey no ownership semantics to the programmer whatsoever, so they should only be used for temporary references that no one will hold on to. If you need to pass or share ownership, that's when our friendly smart pointers come into play. In your code, you should now take this information into consideration and replace your raw pointers with references where a null is not expected and where you are not transferring or sharing ownership. One place where I'm pretty sure you've misused the shared pointer is in the render function:

void Render(std::shared_ptr<Core::Renderer> renderer, std::shared_ptr<Core::Window> window)

I see no reason for the Scene render to take shared ownership of those objects just for the drawing. Unless you have some serious threading going on, there's no way the objects can be destroyed while the scene is rendered. You should be using references in there.

I think you did a good job here and there's little to change. Now about the pointers and memory management...

I was told by an industry professional that smart pointers (like shared_ptr) are frowned upon in game engines

It is true. The game development industry is known for its fear of the Standard C++ Library. From my own experience, for the most part it is just cargo cult from the early days of embedded development for Consoles that had very steep hardware limitations, and from when the Standard Library was still very new and not well implemented.

This is not to say that there aren't a few instances where this fear is justifiable, but in general I think it is very exaggerated. I suggest taking a look at this CppCon talk from last year's conference where some points about "C++ for game development" are discussed.


Now let's get to the point, when should you use a shared pointer, a unique pointer, a raw pointer or a reference?

  • shared_ptr is meant for when the lifetime of an object needs to be shared by distinct owners. The last owner holding a reference to the object will destroy it when it goes away. In your code specifically, who owns the Entities? If they are owned by the Scene, then you certainly don't need a shared pointer, because there's no shared ownership going on!

  • So how about unique_ptr? This one meant for when an object has a single owner during its lifetime. When the owner goes away, it deletes the object. Ownership can be transferred with std::move, but no two object can own the same unique_ptr. Should Scene be using unique_ptr? It could. Your vectors of entities could be storing then by unique_ptr. It would make your code a lot simpler by removing all manual cleanup that you are currently doing. It would also make sure your code never leaks memory in the event of an exception being thrown.

  • And raw pointers and references, where do they fit in this? At the compiler level, a reference and a pointer to an object are the same thing, but it makes a huge difference for the programmer. A pointer has the potential of being nullptr, you can assign null to it explicitly, so we use pointers when we know the object might be null and we are going to check for that. A reference, on the other hand, cannot have null assigned to it and cannot be rebound once initialized, so when we pass a parameter by reference, for instance, we are making it cristal clear to the reader that the object will not be null. NOTE that both a reference and a raw pointer convey no ownership semantics to the programmer whatsoever, so they should only be used for temporary references that no one will hold on to. If you need to pass or share ownership, that's when our friendly smart pointers come into play. In your code, you should now take this information into consideration and replace your raw pointers with references where a null is not expected and where you are not transferring or sharing ownership. One place where I'm pretty sure you've misused the shared pointer is in the render function:

void Render(std::shared_ptr<Core::Renderer> renderer, std::shared_ptr<Core::Window> window)

I see no reason for the Scene render to take shared ownership of those objects just for the drawing. Unless you have some serious threading going on, there's no way the objects can be destroyed while the scene is rendered. You should be using references in there.

Source Link
glampert
  • 17.2k
  • 4
  • 30
  • 89

I think you did a good job here and there's little to change. Now about the pointers and memory management...

I was told by an industry professional that smart pointers (like shared_ptr) are frowned upon in game engines

It is true. The game development industry is known for its fear of the Standard C++ Library. From my own experience, for the most part it is just cargo cult from the early days of embedded development for Consoles that had very steep hardware limitations, and from when the Standard Library was still very new and not well implemented.

This is not to say that there aren't a few instances where this fear is justifiable, but in general I think it is very exaggerated. I suggest taking a look at this CppCon talk from last year's conference where some points about "C++ for game development" are discussed.


Now let's get to the point, when should you use a shared pointer, a unique pointer, a raw pointer or a reference?

  • shared_ptr is meant for when the lifetime of an object needs to be shared by distinct owners. The last owner holding a reference to the object will destroy it when it goes away. In your code specifically, who owns the Entities? If they are owned by the Scene, then you certainly don't need a shared pointer, because there's no shared ownership going on!

  • So how about unique_ptr? This one meant for when an object has a single owner during its lifetime. When the owner goes away, it deletes the object. Ownership can be transferred with std::move, but no two object can own the same unique_ptr. Should Scene be using unique_ptr? It could. Your vectors of entities could be storing then by unique_ptr. It would make your code a lot simpler by removing all manual cleanup that you are currently doing. It would also make sure your code never leaks memory in the event of an exception being thrown.

  • And raw pointers and references, where do they fit in this? At the compiler level, a reference and a pointer to an object are the same thing, but it makes a huge difference for the programmer. A pointer has the potential of being nullptr, you can assign null to it explicitly, so we use pointers when we know the object might be null and we are going to check for that. A reference, on the other hand, cannot have null assigned to it and cannot be rebound once initialized, so when we pass a parameter by reference, for instance, we are making it cristal clear to the reader that the object will not be null. NOTE that both a reference and a raw pointer convey no ownership semantics to the programmer whatsoever, so they should only be used for temporary references that no one will hold on to. If you need to pass or share ownership, that's when our friendly smart pointers come into play. In your code, you should now take this information into consideration and replace your raw pointers with references where a null is not expected and where you are not transferring or sharing ownership. One place where I'm pretty sure you've misused the shared pointer is in the render function:

void Render(std::shared_ptr<Core::Renderer> renderer, std::shared_ptr<Core::Window> window)

I see no reason for the Scene render to take shared ownership of those objects just for the drawing. Unless you have some serious threading going on, there's no way the objects can be destroyed while the scene is rendered. You should be using references in there.