Why does std::list::front result change after creating a new list?

Viewed 141

In the following code, why does list_front change after calling gen_list a second time? gen_list is creating a new list, how does that change a previous list head?

#include <iostream>
#include <list>

std::list<int> gen_list()
{
    static int s_count = 0;
    std::list<int> result;
    for (int i = 0; i < 5; i++)
    {
        result.push_back(s_count++);
    }
    return result;
}

int main()
{
    const auto& list_front = gen_list().front();
    std::cout<<list_front<<"\n";
    gen_list();
    std::cout<<list_front<<"\n";
}

result:

0
9

Demo

2 Answers

You need to bind to the temporary std::list<int> returned by gen_list():

const auto& list = gen_list();
const auto& list_front = list.front();

otherwise, the std::list<int> will be destroyed at the end of the expression and you'll have a dangling reference. Any use of the dangling reference makes your program have undefined behavior.

The problem is that front() returns a reference.

You commented: const refs extend rvalues' lifetime, but front() doesn't provide a rvalue. Here, you have something you can assign to, i.e. an lvalue, so you have actually a reference variable to part of a temporary object whose lifetime ends at the end of that statement.

So your code exhibits undefined behavior.

To extend lifetime of this variable, you need something which will extend lifetime of list - look at Ted Lyngmo's answer.

Related