Search code examples
c++pointersreferenceshared-ptr

Saving a const reference of a list that I get from another class is not working


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


Solution

  • 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.