We're a community of 1077K IT Pros here for help, advice, solutions, professional growth and fun. Join us!
1,076,153 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Start New Discussion Reply to this Discussion

Possible to clear a vector without clearing the data?

I want to re-use a vector<short> over and over in a performance critical loop. I only need the vector size to be reset to zero at the end of the loop. I'm worried that the myVector.clear() takes time to actually clear all the memory. Also, does the myVector.reserve() survive the clear()?

vector<short> myVector;
myVector.reserve(10000);

while(true)
{
    for(int i = 0; i < 10000; ++i)
    {
        myVector.push_back(*something++);
    }
    writeOut(myVector);
    myVector.clear();
}
3
Contributors
3
Replies
12 Hours
Discussion Span
11 Months Ago
Last Updated
4
Views
Question
Answered
sampsont
Newbie Poster
7 posts since Mar 2009
Reputation Points: 10
Solved Threads: 0
Skill Endorsements: 0

What you did is already correct.. the reserve allowed it to survive the clear..

Your vector will have a size of 0 but a capacity of 10000. All information in the vector is lost and cannot be accessed. If an access is attempted, it will assert out of range. Basically it will crash your program if you try to access a position in the vector for any type that is not integral.

vector<string>being accessed will crash your program.
vector<int/short/double/long> being accessed will not crash your program, but every value in the vector will be 0.

for (int I = 0; I < myVector.size(); I++)  //Will do NOTHING if you have cleared it.

for (int I = 0; I < myVector.capacity(); I++)  //Will do 10000 iterations based on your reserved size.

Now I do not currently have a compiler with me to test with iterators so i'm not sure how that would work but I'm sure you can test it:

for (std::vector<T>::iterator it = myVector.begin(); it != myVector.end(); ++it or something of the sort.

triumphost
Practically a Master Poster
625 posts since Oct 2009
Reputation Points: 59
Solved Threads: 55
Skill Endorsements: 1

I'm worried that the myVector.clear() takes time to actually clear all the memory. Also, does the myVector.reserve() survive the clear()?

The clear() function will almost certainly not deallocate any memory, so, yes, the reserved capacity will remain. I say "almost certainly" because the C++ standard doesn't explicitly require that the capacity is preserved, that decision is left to the library implementer (e.g., the compiler-vendor). But I would be extremely surprised to find an implementation of the clear() function that actually deallocates the memory.

One interesting experiment to do, if you want to understand the behavior of the vector class, is to tap into the allocator object (used under-the-hood by the vector class to allocate the memory) and print a message every time a new memory block is allocated. Here is such an example code that you can run and see for yourself:

#include <iostream>
#include <iomanip>
#include <vector>

// This is a custom allocator class (ignore the details)
template <typename T>
class notice_allocator : public std::allocator< T > {
  public:
    template <typename U>
    struct rebind { typedef notice_allocator<U> other; };

    notice_allocator() throw() : std::allocator<T>() { };
    template <typename U>
    notice_allocator(const notice_allocator<U>& rhs) throw() : 
                     std::allocator<T>(rhs) { };

    //redefine the allocate function to issue a notice:
    typename std::allocator<T>::pointer allocate (typename std::allocator<T>::size_type n, void* hint = 0) {
      std::cout << " ******* Allocated new memory ******* " << std::endl;
      return std::allocator< T >::allocate(n,hint);
    };
};

int main() {

  std::vector<int, notice_allocator<int> > v;

  for(int i = 0; i < 100; ++i) {
    for(int j = 0; j < i; ++j)
      v.push_back(j);          // push-back 'i' elements on the vector.
    std::cout << "Size = " << std::setw(6) << v.size() 
              << "\t Capacity = " << std::setw(6) << v.capacity() << std::endl;
    v.clear();  // clear the vector.
    std::cout << "Size = " << std::setw(6) << v.size() 
              << "\t Capacity = " << std::setw(6) << v.capacity() << std::endl;
  };

  return 0;
};

On my computer, although the above code calls the push_back function about 5000 times, it actually allocates memory only 8 times.

Now, let me correct triumphost a little bit here.

What you did is already correct.. the reserve allowed it to survive the clear..

The use of reserve() has little to do with it. Whether you used reserve or not, the point is that the capacity (actual amount of allocated memory) is very unlikely to get deallocated when you call clear(), whichever way that capacity was acquired (either through reserve() or by adding elements to the vector with resize() or push_back() or whatever).

You can pretty much count on the fact that the clear function will not deallocate any memory. In fact, on the contrary, if you want the memory to be deallocated, you have to force it (you have to use a trick like swapping your vector with a temporary, newly-created vector object).

All information in the vector is lost and cannot be accessed.

The information is still there, and you could access it in a hacker-way. But, yeah, through normal channels and for all practical purposes, the information is lost. But, in reality, of course, no computing time is wasted at "erasing" the information.

If an access is attempted, it will assert out of range.

If you use the at() function, it should throw a std::out_of_range exception. But any other access method is not required (and usually won't) check for an out-of-range condition (but some implementation will assert the condition when compiling and running in debugging mode).

Basically it will crash your program if you try to access a position in the vector for any type that is not integral.

By "integral", I think you meant to say POD-type (Plain-Old-Data type), that's the standard name for an object of a primitive type (int, float, etc.) or any simple struct / union made up of only such primitives (or other POD-types). And, attempting an access outside the range (but still within the capacity) is going to be "undefined behavior", which is likely to be a crash, or just memory corruption.

vector<int/short/double/long> being accessed will not crash your program, but every value in the vector will be 0.

Why 0? There is no reason for that memory to be zero. Only some debugging environments will actually waste time filling uninitialized memory with 0 values. If you access memory outside the range, the value is going to be whatever was there before (which is completely arbitrary, or random).

mike_2000_17
21st Century Viking
Moderator
3,136 posts since Jul 2010
Reputation Points: 2,062
Solved Threads: 625
Skill Endorsements: 41

Perfect! Much thanks!

sampsont
Newbie Poster
7 posts since Mar 2009
Reputation Points: 10
Solved Threads: 0
Skill Endorsements: 0
Question Answered as of 11 Months Ago by mike_2000_17 and triumphost

This question has already been solved: Start a new discussion instead

Post: Markdown Syntax: Formatting Help
 
You
View similar articles that have also been tagged:
 
© 2013 DaniWeb® LLC
Page rendered in 0.1208 seconds using 2.71MB