Here's a working version of what I'm doing.
#include <memory>
using namespace std;
struct thing {
int blah;
};
struct parentObj {
parentObj(thing & incomingThing) : isThisOK(incomingThing) {};
thing & isThisOK;
};
int main()
{
shared_ptr<thing> thingInstance = make_shared<thing>();
shared_ptr<parentObj> theObj = make_shared<parentObj>(*thingInstance);
}
I like assigning a shared pointer to a reference of it's type. (ctrl+f isThisOK)
Are there unintended consequences here? Should I be using a weak pointer?
It is just as okay as this:
#include <memory>
using namespace std;
struct thing {
int blah;
};
struct parentObj {
parentObj(thing& incomingThing) : isThisOK(incomingThing) {};
thing& isThisOK;
};
int main()
{
thing thingInstance;
shared_ptr<parentObj> theObj = make_shared<parentObj>(thingInstance);
}
Just like function parameter should, by default, be agnostic of the ownership strategy unless needed, I would say that what you're doing is right, and even recommend it given a particular case. If your object is agnostic of the ownership strategy unless needed, this is usually the way to go.
Just be aware of two things:
parentObj
should be considered invalid.std::unique_ptr
instead, since the owner of a unique pointer is much easier to track. When reading a code with unique pointers, you can easily spot where the lifetime should end and where it is transferred. With a shared one, not so clear. With a unique pointer, you can set the boundary "statically", let's say, a parentObj
is invalid after the thing
died, and it should be clear when the lifetime of both has ended. If you have a shared pointer, I would recommend you have a way to check the validity at runtime before using the parentObj
.I would use a std::weak_ptr
only if by design parentObj
should check the validity of thing
at runtime, and users of parentObj
cannot check the validity of thing
. Usually, there is a place in the code that you can be sure when thing
and parentObj
start and end their lifetime. If you have a place where you know their lifetime, then I would say that it's the responsibility of that code to check the validity of thing
and parentObj
and let those two type be simpler.