My code is a bit more complicated, but I think the structure can be boiled down to this, imagine the following two classes:
class Foo {
std::list<std::shared_ptr<SomeType>> listOfType;
const std::list<std::shared_ptr<SomeType>>& getList() const {
return listOfType;
}
}
class A {
std::shared_ptr<Foo> foo;
Foo getFoo() {
return (*foo);
}
}
Now consider these three options, after the A class has filled the Foo's list:
A a;
// Do something with a, fills the list inside the foo shared pointer
// Option 1, save the copy of foo, then get the const reference of the list
Foo f = a.getFoo();
const std::list<std::shared_ptr<SomeType>>& fList = f.getList();
// Option 2, get a copy of the list directly from the returned copy of foo
std::list<std::shared_ptr<SomeType>> fList = a.getFoo().getList();
// Option 3, get the const list reference directly from the returned copy of foo
const std::list<std::shared_ptr<SomeType>>& fList = a.getFoo().getList();
Option 3 returns an empty list, the other two options return the list with the expected content.
The reason I'm creating this question is to know whether there is a problem that I don't see with this code (considering all the references and shared pointers, etc), otherwise it will be a problem with code, which would be beyond the scope of the question.
Thanks
Foo getFoo() {
return *foo;
}
In this member function, you are returning a temporary which is a prvalue in the calling expression. Because you call .getList() on it, it will get materialized and become a xvalue (expiring value) and as soon as the expression finishes, it will be destroyed and as you are capturing the reference of the returned list from a temporary object in the third 'option', it will become a dangling reference.
Foo & getFoo() {
return *foo;
}
However if you return a reference, it will be treated as a lvalue in the calling expression so the list won't be a dangling reference.