Coop
Coop

Reputation: 11

Strange memory management using vector and QVector

I am developing an application based on QT, I need to use vectors in a dynamic (QVector ). When checking the size of the vector, this was higher than it should, I tested with STL vector and the result is the same. Below I present code the problem with STL vector. This situation prevents us from knowing the actual size of the vector and use it properly. How to fix?. Thank you for your help.

The code is:

double PI = 3.1415926536, delta = PI/(100/2);
vector<double> A(0);
vector<double> B(0);
cout<<"Capacity A = "<<A.capacity()<<"; Capacity B = "<<B.capacity()<<endl;
for (int i = 0; i < 100; i++) {
    A.push_back(i*delta);
    B.push_back( sin( A[i]  ) );
    cout<<"A("<<i<<") = " <<A[i]<<"; B("<<i<<") = " <<B[i]<<" "<<"Size A = "<<A.capacity()<<"; Size B = "<<B.capacity()<<endl;
}

for (int i = 0; i < A.capacity(); i++) {
   cout<<"A("<<i<<") = " <<A[i]<<"; B("<<i<<") = " <<B[i]<<" "<<"Size A = "<<A.capacity()<<"; Size B = "<<B.capacity()<<endl;
}
cout<<"Size A = "<<A.capacity()<<"; Size B = "<<B.capacity()<<endl;

The output is:

Capacity A = 0; Capacity B = 0
A(0) = 0; B(0) = 0 Size A = 1; Size Y = 1    
A(1) = 0.0628319; B(1) = 0.0627905 Size A = 2; Size B = 2    
A(2) = 0.125664; B(2) = 0.125333 Size A = 4; Size B = 4    
A(3) = 0.188496; B(3) = 0.187381 Size A = 4; Size B = 4    
.    
A(99) = 6.22035; B(99) = -0.0627905 Size A = 128; Size B = 128    
.    
A(126) = 0; B(126) = 1.31947 Size A = 128; Size B = 128    
A(127) = 0; B(127) = 1.3823 Size A = 128; Size B = 128   
Size A = 128; Size B = 128

Upvotes: 1

Views: 1110

Answers (2)

stinky472
stinky472

Reputation: 6797

Why are you interested in capacity? Are you focusing on memory usage? The capacity method is not needed otherwise, and you only need to concern yourself with size.

If we're talking about capacity details, how the capacity changes is up to vendor implementation. The fact that yours reallocates arrays based on powers of 2 may not apply to all cases: I've seen some implementations scale by a factor of 150%, for example, rather than 200%.

capacity will often be greater than size, and sometimes considerably greater (ex: double the number of elements). This is because vectors are growable, contiguous sequences (they're array-based). The last thing you want if you care at all about performance is for every push_back/insert/erase to trigger a memory allocation/deallocation, so vector often creates an array bigger than is immediately necessary for subsequent insertions. It's also worth noting that the clear method will not necessarily do anything to affect capacity, and you might want to look at the shrink-to-fit idiom (http://www.gotw.ca/gotw/054.htm).

If you want absolute control over the capacity so that you have a perfect fit, you can make use of the reserve method to allocate a specific capacity in advance. That only works well though if you can anticipate the number of elements you will be putting into your vector in advance.

Upvotes: 0

Qaz
Qaz

Reputation: 61970

What you're seeing is std::vector's ability to scale. One of the things they put in to make it work faster in general cases was to reserve more memory than what is needed, so that it doesn't have to keep reserving memory each time you use push_back.

As you can see, more is reserved the larger it gets. capacity is the function that tells you this amount. You can test this theory out by using reserve. It will tell the vector how much memory to reserve, after which capacity will retrieve that number if no operations are made (which could cause another change in reserved memory). reserve is generally useful if you're about to push_back a large number of elements and you want the vector to only reserve enough memory once, instead of however many times it would have automatically.

The function you're looking for is size, which gives you the number of elements in your vector. The associated function with this is resize, as reserve was to capacity. That is to say, when you call resize (10), if you had 5 elements before, you'll gain 5 default-initialized new ones, and size returns 10.

Upvotes: 4

Related Questions