Assume there is a global Foo
object,
struct Foo {
int i;
~Foo() { std::cout << "gone: " << i << std::endl; }
};
Foo globalFoo{7};
that it can be retrieved via a function that returns it by reference,
Foo& getFoo() {
return globalFoo;
}
and that there's also a factory function to make a different Foo
out of thin air,
std::unique_ptr<Foo> makeFoo() {
return std::make_unique<Foo>(5);
}
The above is unchangeable.
In client code, whether one should use makeFoo
or getFoo
is determined by a runtime bool
.
int main()
{
bool b{false};
std::cin >> b;
/* type */ foo = b
? /* via getFoo */
: /* via makeFoo */;
}
What is the appropriate way to deal with this scenario?
I can tell that this is not the way:
auto& foo = b
? getFoo()
: *makeFoo();
because foo
is a dangling reference right after its created, as the temporary result of makeFoo()
, the unique_ptr
will be destoryed, thus taking the managed Foo
with it.
This too is not the way:
auto& foo = b
? getFoo()
: *makeFoo().release();
because the object *makeFoo().release()
is leaked, unless I manually delete
it.
You can wrap the result in shared_ptr
with a deleter that does nothing in case this is a global object. Unlike for unique_ptr
, deleter of shared_ptr
is not a part of the type of the smart pointer itself, so the type will be the same for both cases.
Something like this:
auto foo = b ? std::shared_ptr(&/* via getFoo */, [](Foo*){})
: std::shared_ptr(/* via makeFoo */);