Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

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

like image 908
Epic Avatar asked Mar 10 '20 14:03

Epic


People also ask

How do I get the first element of a list in CPP?

list front() function in C++ STL. Parameters: This function does not accept any parameter, it simply returns a reference to the first element in the list container. Return Value: This function returns a direct reference to the first element in the list container.

What is CPP list?

Lists are sequence containers that allow non-contiguous memory allocation. As compared to vector, the list has slow traversal, but once a position has been found, insertion and deletion are quick. Normally, when we say a List, we talk about a doubly linked list.

How do I create a list in CPP?

Default constructor std::list::list()- It creates an empty list, that, with zero elements. Fill constructor std::list::list()- It creates a list with n elements and assigns a value of zero (0) to each element. Range constructor std::list::list()- creates a list with many elements in the range of first to last.

Should I use std :: list?

From a performance standpoint, the best reason to use std::list is so that when later on your app is suffering badly for performance and needs "an optimziation pass", you can replace it with another data structure and look like a hero.


Video Answer


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.

like image 152
Ted Lyngmo Avatar answered Nov 14 '22 21:11

Ted Lyngmo


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.

like image 31
Marek R Avatar answered Nov 14 '22 21:11

Marek R