Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List and list elements, where are stored?

Tags:

c++

Given this piece of code:

#include <list>
(void) someFunction(void) {
    list <int> l;
    l.push_back(1);
}
  • Where are the elements of the list stored? Stack? Heap?
  • How can I do to empirically check that values are in stack or heap?
  • This function can returns the list? Edited If I declare function as list, can function returns list with out problems?

Sample (returning list):

#include <list>
list<int> someFunction(void) {
    list <int> l;
    l.push_back(1);
}

...
l2 = someFunction();
l2.push_back(2);
like image 987
dani herrera Avatar asked Jan 16 '12 15:01

dani herrera


3 Answers

Where are the elements of the list stored? Stack? Heap?

List elements are stored on the heap. You can see this following your debugger down on the push_back method call. The easiest to see it is to store objects rather than POD type, and log the constructor. You'll need a copy constructor as they are get copied. The allocation happens with the template argument allocator, which you can specify or without specifying it it would go with the default heap allocation.

How can I do to empirically check that values are in stack or heap?

You can check this with push_back elements from the stack:

std::list<int> my_list;
int a = 10;
my_list.push_back(a);
a = 11;
assert(*my_list.begin() == 10);

This function can returns the list?

In C++ there are two ways to pass data around: by reference or by value. If you're function looks like this,

list<int> func()
{
  list<int> res;
  res.push_back(10);
  return res;
}

then you're passing the list by value, which means that the compiler will call the list's copy constructor which also copies all the values in the list. As the function returns, after it copies the list, the "res" list's destructor will be called, releasing all its elements. However if you do this:

list<int>& func()
{
      list<int> res;
      res.push_back(10);
      return res;
}

You're code will fail as you return the reference to your "res" list, which will be already destroyed at the end of its scope, so you're reference will be invalid.

The problem with the first solution can be performance. You can also do that without the call of the copy constructor like this:

void func(list<int>& res)
{
  res.push_back(10);
}

list<int> list_to_fill;
func(list_to_fill);

In this case, there's no copying and it should be faster as there's only one list creation.

like image 115
progician Avatar answered Sep 24 '22 20:09

progician


Where are the elements of the list stored? Stack? Heap?

The elements held by the list are typically dynamically allocated so this will be on the heap.

This function can returns the list?

No it cannot, you declared your function with a return type of void.

How can I do to empirically check that values are in stack or heap?

The only way to be really sure is to peek into the std::list implementation to see what it's really doing. But you don't really need to care about this since it's an implementation detail.

like image 37
greatwolf Avatar answered Sep 24 '22 20:09

greatwolf


The answer you selected is incorrect about 1 thing...

returning a list does not call the list's copy constructor.

list<int> func()
{
  list<int> res; // &res returns 0x7fff183f0900
  res.push_back(10);
  return res;
}

list<int> l = func();   // &l also returns 0x7fff183f0900 (no copy)

You can double check this by printing &res in the function and &l outside the function.

The compiler is optimized to pass through returned objects without making copies, otherwise every single non-pointer object returned would be copied, which would be insane.

like image 21
CompEng88 Avatar answered Sep 25 '22 20:09

CompEng88