I am having a quite common problem, I have a class that must store a non-owning pointer to a different class object.
I know that:
- The lifetime of the reference object is guaranteed to outlive the instance.
- The referenced object is passed in a constructor and does not change with the exception of moves or assignment.
- It is never invalid.
- It is used in many methods.
- It can be shared by many instances.
Think of e.g. a logger
class which is not global.
These points lead me to this solution using a reference variable which guarantees validity:
struct Foo{};
struct Bar{
Bar(Foo& foo):m_foo(foo){}
Foo& m_foo;
};
The big downside is Bar
is unnecessarily almost immutable - no assignment, no move.
The usual thing I did was to store Foo
as a pointer instead. This solves most of the issues except that it is no longer very clear that the pointer is always valid. Furthermore it adds a new small one that it can be invalidated in any method, which should not happen. (Making it const has the same downside as &
). That makes me add assert(m_foo)
to every method for the peace of mind.
So, I was thinking about just storing std::reference_wrapper<Foo>
, it is always valid and it keeps Bar
mutable. Are there any downsides compared to a simple pointer? I know that any method can still point it to e.g. a local variable but let's say that does not happen because it is perhaps hard to obtain a new valid instance of Foo
. At least it is harder than simple =nullptr;
I know this approach is used for containers like std::vector
so I assume it is okay, but I would like to know if there is any catch I should look for.
Aucun commentaire:
Enregistrer un commentaire