Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: General question about references, pointers, and unique_ptr  (Read 3715 times)

0 Members and 1 Guest are viewing this topic.

Lideln

  • Newbie
  • *
  • Posts: 5
    • View Profile
General question about references, pointers, and unique_ptr
« on: December 21, 2013, 11:37:15 am »
Hi there!

I bought the SFML book and started to read it. It is very interesting! It also quickly speaks of the unique_ptr feature of C++ 11, and advises to use it for asset management (which I did).

But then it came to me that when I started to study C++ , it was like 10 years ago, and at the time I was advised to use pointers and to not forget to delete them when not needed anymore.

Then I stopped using C++ after only a few months after learning it, to go web (PHP et al)

But today, I'm getting back to C++ with a friend, and I saw many people telling "use pointers only if you do arithmetics, and use references everywhere else".

What is unclear to me is how everything should be stocked (as member variables) in a game engine:
- plain objects (I think only in the object that creates them, like Game for WindowRenderer, AssetManager, ...)
- references (need to be set exclusively in the ctor, unless I'm mistaken?)
- pointers
- or even std::unique_ptr like it is advised for asset management in the book

The book doesn't talk about that, maybe because it is not the main topic.
Does anyone know of a game engine tutorial that emphasis on this particular problem? I would really like to use "best practices" and do things the right way. And honestly, references and pointers (and not unique_ptr) confuse me a lot for the moment!

Thank you :)

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: General question about references, pointers, and unique_ptr
« Reply #1 on: December 21, 2013, 04:24:09 pm »
The way how C++ is used has fundamentally changed over the years, even long before C++11. A lot of paradigms and idioms have evolved at the beginning of the 2000s. You should not be afraid of throwing old practices (such as manual memory management) away.

Here is how I would use the different types:
  • Plain objects: The default, their memory is managed automatically through RAII. You should use them unless you have a reason to use indirections.
  • Pointers: Passive indirections, you need them when you refer to other objects. Crucial: do never let raw pointers own resources, i.e. don't combine them with new and delete. Pointers should be passive, they are not responsible of the pointee's memory.
  • References: They are constant (you can't modify the referencee after initialization). You can use them for indirections that don't require the flexibility of pointers (mutability, the nullptr state, dereferencing, pointer arithmetic). Mostly references are used for parameters, when they can't be nullptr.
  • Unique pointers: Use them when you need pointers that own their memory. There are reasons why you can't work with automatic objects: polymorphism, non-copyable and non-movable types, delayed initialization, reduction of compile-time dependencies (PImpl idiom). std::unique_ptr should be the default choice when you allocate objects dynamically.
  • Shared pointers: std::shared_ptr is only required in the rare case of shared ownership, where multiple objects are responsible of deallocation. Do not use this smart pointer unless really necessary; it comes at a performance cost and may lead people to think less about ownership semantics.
  • Copied pointers: Not in the standard, but I personally find them extremely useful when you want to combine the advantages of automatic objects (that have copy semantics) with those of pointers. I developed aurora::CopiedPtr that fills this hole -- this site explains a lot about semantics, too.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Lideln

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: General question about references, pointers, and unique_ptr
« Reply #2 on: December 21, 2013, 10:33:50 pm »
Hi Nexus!

Thank you for the detailed answer. I understood a few things, but not everything I guess.

In your POV, I should always use plain objects, when I can't then unique_ptr, and if I still can't then pointers. References only for methods parameters.

I think I really need to be pointed to a tutorial that shows the mechanics, because it's still confusing.

Say I have these typical (??) game engine classes:
- A Game instance, that manages a bit of everything, the heart of the game in some way
- A few State instances, that represent the different game states (splash screen, menu, in-game, ...)

I'm still unsure how to define the member variables (or methods parameters), regarding RenderWindow, AssetManager, etc.

1) Plain objects, public visibility, in the Game instance, and a static instance() accessor so that we can retrieve the game easily?

2) Do as I were once told: never use public members. Therefore, RenderWindow and AssetManager instances are protected and will be passed by reference to the StateManager, so that it can also pass them by reference to the States

3) Any other solution...

For now, I went with solution 1) in my code, because I fought so much with solution 2) earlier, that I decided to go with the easiest possible solution...

Is there a preferred way to do it? But then, when do the unique_ptr come into play? (I only use them in the AssetManager, thanks to the SFML book advices)

I'm sorry for my question. But C++ is really a pain in my back! :) I'm used to Java, Javascript, and PHP, which are way easier to use... No question to ask yourself: in Java everything is a pointer. Piece of cake :) In PHP objects are passed by reference and primitive types variables are passed by value. Piece of cake :)

I really need to dive into a (recent) game engine tutorial. I found the one of GQE, which is interesting but incomplete.

Best regards,

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: General question about references, pointers, and unique_ptr
« Reply #3 on: December 22, 2013, 12:52:12 pm »
In your POV, I should always use plain objects, when I can't then unique_ptr, and if I still can't then pointers. References only for methods parameters.
No. There are mainly two use cases:
  • An object owns another one -> automatic object or smart pointer
  • An object refers to another one -> pointer or reference
I think I really need to be pointed to a tutorial that shows the mechanics, because it's still confusing.
Tutorials on the Internet mostly suck, as they omit important background knowledge. You should read a good C++ book, such as the C++ Primer or Thinking in C++ (which is available as free e-book).

1) Plain objects, public visibility, in the Game instance, and a static instance() accessor so that we can retrieve the game easily?
No, very bad idea. Public members break encapsulation, and static/global/singleton access breaks modularity and locality. The "easily" is tempting, but it comes at a high price.

2) Do as I were once told: never use public members. Therefore, RenderWindow and AssetManager instances are protected and will be passed by reference to the StateManager, so that it can also pass them by reference to the States
Why protected and not private? But yes, it looks like this is the way to go. What I would try is to reduce dependencies as much as possible; only give access to the window in places that really need it (typically event handling and drawing).

You mentioned the SFML book, there we also show one possible way to pass around the dependencies (through the State::Context class). It's certainly not the only way, but have you tried something similar? It's also difficult to give concrete advice without knowing your current design and the different classes/responsibilities in your project.

Is there a preferred way to do it? But then, when do the unique_ptr come into play? (I only use them in the AssetManager, thanks to the SFML book advices)
As mentioned in the first post, there are some situations where you actually need smart pointers and automatic objects don't work (or are less convenient). Don't use unique_ptr for the sake of having it used :)

I'm sorry for my question. But C++ is really a pain in my back! :) I'm used to Java, Javascript, and PHP, which are way easier to use... No question to ask yourself: in Java everything is a pointer. Piece of cake :) In PHP objects are passed by reference and primitive types variables are passed by value. Piece of cake :)
Yes, C++ is truly on another difficulty level. Unlike GC languages, it forces you to think about ownership semantics. While this sometimes makes code more complicated, it's not an inherently bad thing, because you begin to think more about how to design your application. And you can see in the code whether an object actually owns another object, or just refers to it in a passive way. But of course, it may take some time to get used to it.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

 

anything