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();
}

Recommended Answers

All 3 Replies

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.

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).

Perfect! Much thanks!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.