My personal preference, be it C, C++, Java, .NET, whatever, is to have functions either return unique ownership (normally a new object, which is then the sole responsibility of the caller), or to return a reference/pointer to something the API still owns and manages. In C++ `unique_ptr` and raw pointers fulfil that nicely.
For function parameters, the same deal where possible, the API either takes ownership, or just uses the reference for a fixed duration, normally the function call itself.
2 hours ago, Tim Leijten said:
E.g. addNewGameObjectToScene. It would create a new object, add it to the scene, and return a pointer. But there is one obvious problem, there is no way to check if the returned pointer is valid. Because the newly created object could be deleted at any point, and then the pointer is invalid and using it would cause crashes. Therefore, to me it would make sense to use smart_pointers to fix that.
Sounds more like a `create`. I think the problem here is the "deleted at any point". What is able to delete it, why is it? Are you multi-threading the game logic? You definitely don't want an API design where a pointer/reference/etc. gets invalidated by some other thread, maybe before a create/get function even returns.
A solution I used with a couple of things was to say my object references must stay valid during a particular update frame (I was essentially storing them in std::vector). This meant any pointer within an update was guaranteed safe, but I had to use unique ID's to track specific things between frames.
1 hour ago, ongamex92 said:
You could use handles. ... If you want the pointer approach shared_ptr+weak_ptr could do the thing for you.
I think it is important though, even if you do use "shared_ptr" or "handle", or even in languages like Java and .NET, to try and stick to a single ownership model for object lifetime where possible, as it is easier to think through, and even garbage collector languages have things it does poorly (Close/Dispose/etc.) or the possibility of memory leaks (e.g. forgetting to remove things from collections).
e.g. in this case you object is probably still "owned" by the scene, and once removed it is marked "dead", removed from the scene collections, any getter fr it returns null, it's not rendered, no physics, no updates, etc. and any remaining references are mostly just a safe way for other objects to see it "is dead" in a safe way.
2 hours ago, Tim Leijten said:
if I should use smart pointers, will it impact performance or drive people away from using my api?
`unique_ptr` has literally zero cost, `shared_ptr` you probably want `enable_shared_from_this` (or traditional intrusive ref counting). You probably regardless want to avoid using heap dynamic allocations for objects. The fastest is generally going to be a vector<T> of values, due to continuous memory, but sometimes that is not practical.