0

i have a project in c++03 that have a problem with data structure: i use vector instead of list even if i have to continuously pop_front-push_back. but for now it is ok because i need to rewrite too many code for now.

my approach is tuo have a buffer of last frame_size point always updated. so each frame i have to pop front and push back. (mayebe there is a name for this approach?)

so i use this code:

Point apoint;  // allocate new point
apoint.x = xx;
apoint.y = yy;

int size = points.size()
if (size > frame_size) {
    this->points.erase( points.begin() );  // pop_front
}
this->points.push_back(apoint);

i have some ready-to-use code for an object pool and so i thought: it is not a great optimization but i can store the front in the pool and so i can gain the allocation time of apoint.

ok this is not so useful and probably it make no sense but i ask just to educational curiosity: how can i do that?

how can i store the memory of erased element of a vector for reusing it? does this question make sense? if not, why?

.. because erase does not return the erased vector, it return:

A random access iterator pointing to the new location of the element that followed the last element erased by the function call, which is the vector end if the operation erased the last element in the sequence.

Community
  • 1
  • 1
nkint
  • 11,513
  • 31
  • 103
  • 174
  • 2
    If you continuously `pop_front`, and do not want to use `list`, then why not `std::deque`? – Sebastian Mach Feb 27 '12 at 11:08
  • the problem is that i have a lot of utilities that use std::vector so i need to open the repository of utility, fork it, and template (or rewrite) everything that take a vector to make it usable for list or deque – nkint Feb 27 '12 at 11:11
  • Is the creation of Point heavy-weight ? You are storing objects and not pointers to objects in the vector. If you want to save the objects in the pool then it is a good idea to store them as pointers instead of objects. – Jagannath Feb 27 '12 at 11:19
  • If you a `push_back()` immediately after an `erase()`, then there's already memory allocated for the new object. Vector doesn't shrink the capacity when you erase from it. The object won't be constructed in the exact same spot, though, but that's probably not the point, right? – jrok Feb 27 '12 at 11:22
  • @Jagannath: i think Point it's not so heavy but for an object pool is a good thing thought as if it is heavy, isn't it? thanks for advice. – nkint Feb 27 '12 at 11:39
  • @jrok: i think the heavy part that an object pool should help to is the construction of new object, not only memory, mayebe i didn't explain myself well.. – nkint Feb 27 '12 at 11:40

2 Answers2

2

i have some ready-to-use code for an object pool ... how can i do that?

Using a vector, you can't. A vector stores its elements in a contiguous array, so they can't be allocated one at a time, only in blocks of arbitrary size. Therefore, you can't use an object pool as an allocator for std::vector.

how can i store the memory of erased element of a vector for reusing it? does this question make sense? if not, why?

The vector already does that. Your call to erase moves all the elements down into the space vacated by the first element, leaving an empty space at the end to push the new element into.

As long as you use a vector, you can't avoid moving all the elements when you erase the first; if that is too inefficient, then use a deque (or possibly a list) instead.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
1

I'm not sure to understand what you want to do, but this should be functionnally equivalent to what you wrote, without constructing a temporary Point instance:

// don't do this on an empty vector
assert (points.size() > 0);

// rotate elements in the vector, erasing the first element
// and duplicating the last one
copy (points.begin()+1, points.end(), points.begin());

// overwrite the last element with your new data
points.back().x = xx;
points.back().y = yy;

EDIT: As Mike Seymour noted in the comments, neither this solution nor the approach proposed in the question cause any new memory allocation.

François Févotte
  • 19,520
  • 4
  • 51
  • 74
  • The last 2 statements should be inside the if condition ? – Jagannath Feb 27 '12 at 11:28
  • Just remove the if condition and should be want @nkint wants. – Jagannath Feb 27 '12 at 11:33
  • @Jagannath both ways should be equivalent, but you're right: yours is more elegant and compact. – François Févotte Feb 27 '12 at 11:36
  • in this way i have no need to use the pool. but in general case, if i wanto to use the pool? how can i do it? – nkint Feb 27 '12 at 11:50
  • 1
    Note that the code in the question doesn't allocate new memory either - `vector` will only allocate when it needs to grow. Using `copy` may be less efficient, since it explicitly copies the objects, whereas `erase` could move them. – Mike Seymour Feb 27 '12 at 11:53
  • @MikeSeymour is it not possible that calling `erase()` would cause the vector to free some space since its size decreases? Otherwise, you're right: `erase` could move objects instead of copying them (but since Point looks like a plain `struct`, I doubt moving would be more efficient than copying in this case). – François Févotte Feb 27 '12 at 12:54
  • @Francesco: Erasing any element except the first can't cause reallocation, since references to elements before the erased one must be preservec. Theoretically, an insane implementor could check for the special case of erasing the first element and reallocate in that case; I doubt any actual implementor would think that saving the memory of one element in one special situation is worth the performance cost and memory fragmentation involved. – Mike Seymour Feb 27 '12 at 13:00
  • Point class is a struct of coordinate and a lot of method for vector algebra. is this important for reallocation? – nkint Feb 27 '12 at 14:20