Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an equivalent of vector::reserve() for an std::list?

Tags:

c++

list

stl

vector

I have a class that looks like this:

typedef std::list<char*> PtrList;
class Foo
{
public:
   void DoStuff();
private:
   PtrList m_list;
   PtrList::iterator m_it;
};

The function DoStuff() basically adds elements to m_list or erases elements from it, finds an iterator to some special element in it and stores it in m_it. It is important to note that each value of m_it is used in every following call of DoStuff().

So what's the problem? Everything works, except that profiling shows that the operator new is invoked too much due to list::push_back() called from DoStuff().

To increase performance I want to preallocate memory for m_list in the initialization of Foo as I would do if it were an std::vector. The problem is that this would introduce new problems such as:

  1. Less efficient insert and erase of elements.
  2. m_it becomes invalid as soon as the vector is changed from one call to DoStuff() to the next. EDIT: Alan Stokes suggested to use an index instead of an iterator, solving this issue.

My solution: the simplest solution I could think of is to implement a pool of objects that also has a linked-list functionality. This way I get a linked list and can preallocate memory for it.

Am I missing something or is it really the simplest solution? I'd rather not "re-invent the wheel", and use a standard solution instead, if it exists.

Any thoughts, workarounds or enlightening comments would be appreciated!

like image 248
Eitan T Avatar asked May 20 '12 14:05

Eitan T


People also ask

What is vector Reserve?

std::vector::reserveRequests that the vector capacity be at least enough to contain n elements. If n is greater than the current vector capacity, the function causes the container to reallocate its storage increasing its capacity to n (or greater).

Does vector Reserve take up memory?

vector::reserve does allocate memory, so your question about reserving memory without allocating is incorrect. The point is that reserving memory can be done without changing the vectors size. Basically a vector has two sizes, it's size and it's capacity.

How do you reserve a memory vector?

An std::vector manages its own memory. You can use the reserve() and resize() methods to have it allocate enough memory to fit a given amount of items: std::vector<int> vec1; vec1. reserve(30); // Allocate space for 30 items, but vec1 is still empty.

What is the difference between std::list and std::vector?

Hence std::list provides some extra functions for Sorting, Splicing, Removing elements and identifying unique elements. Vector provides the random access and hence can be used with STL algorithms that uses Random Access Iterators.


2 Answers

I think you are using wrong the container.

If you want fast push back then don't automatically assume that you need a linked list, a linked list is a slow container, it is basically suitable for reordering.

A better container is a std::deque. A deque is basically a array of arrays. It allocates a block of memory and occupies it when you push back, when it runs out it will allocate another block. This means that it only allocates very infrequently and you do not have to know the size of the container ahead of time for efficiency like std::vector and reserver.

like image 77
111111 Avatar answered Sep 24 '22 20:09

111111


You can use the splice function in std::list to implement a pool. Add a new member variable PtrList m_Pool. When you want to add a new object and the pool is not empty, assign the value to the first element in the pool and then splice it into the list. To erase an element, splice it from the list to the pool.

But if you don't care about the order of the elements, then a deque can be much faster. If you want to erase an element in the middle, copy the last element onto the element you want to delete, then erase the last element.

like image 26
Derek Ledbetter Avatar answered Sep 23 '22 20:09

Derek Ledbetter