How to free memory for vector of vectors (C++) - c++

I have a vector<vector<double>> elem and I want to deallocate its memory many times in my program.
I tried using
vector<vector<double>>().swap(elem);
Or even a for cicle
for(int i=0; i<elem.size();i++)
vector<double>().swap(elem[i]);
vector<vector<double>>().swap(elem);
elem.resize(dim, vector<double>(0));
(I want the first dimension to be a certain number dim)
But when I call
cout<<elem[0].size();
numerous times in my program, the output keeps growing, even if I've just used the aforementioned method. This issue isn't present with the "main" size of the vector.
i.e.
cout<<elem.size();
always outputs dim
EDIT: I know about clear() but I want to deallocate the vector, shrink_to_fit() doesn't work either. Also this is implemented in a function out of the main one, as follows:
void arrayReset(vector<vector<double>> elem) {
for(int i=0; i<elem.size();i++)
vector<double>().swap(elem[i]);
vector<vector<double>>().swap(elem);
elem.resize(dim, vector<double>(0));
}

Your new function void arrayReset(vector<vector<double>> elem) { gets a COPY of your vector and [possibly] cleans it; you never see it in the calling function.
If you pass your vector by reference, you would manipulate the original vector.

How to free memory for vector
The way is the same for all vectors regardless of the element type.
Step 1: Remove the elements of the vector. Simplest way is the clear member function. After this step, the size member function will return 0.
Step 2: Call shrink_to_fit member function which requests the memory to be deallocated. After this step, capacity may return 0.
Technically, shrink_to_fit is a request that is not required to be honoured by the language implementation. The only guaranteed way to deallocate the memory is to destroy the vector. Example:
{
std::vector<std::vector<double> vector;
// use vector here
}
// memory has been deallocated
I want to deallocate its memory many times in my program.
Note that this is typically slower than not deallocating many times. I recommend making sure that you want something that is actually useful.

Related

Vector of pointers undefined behaviour

I'm trying to make a vector of pointers whose elements are pointing to vector of int elements. (I'm solving a competitive programming-like problem, that's why it sounds kinda nonsense).
but here's the code:
#include <bits/stdc++.h>
using namespace std;
int ct = 0;
vector<int> vec;
vector<int*> rf;
void addRef(int n){
vec.push_back(n);
rf.push_back(&vec[ct]);
ct++;
}
int main(){
addRef(1);
addRef(2);
addRef(5);
for(int i = 0; i < ct; i++){
cout << *rf[i] << ' ';
}
cout << endl;
for(int i = 0; i < ct; i++){
cout << vec[i] << ' ';
}
}
When I execute the code, it's showing weird behaviour that I don't understand. The first element of rf (vector<int*>) seems not pointing to the vec's (vector<int>) element, where the rest of the elements are pointing to it.
here's the output when I run it on Dev-C++:
1579600 2 5
1 2 5
When I tried to run the code here, the output is even weirder:
1197743856 0 5
1 2 5
The code is intended to have same output between the first line and the second.
Can you guys explain why it happens? Is there any mistake in my implementation?
thanks
Adding elements to a std::vector with push_back or similar may invalidate all iterators and references to its elements. See https://en.cppreference.com/w/cpp/container/vector/push_back.
The idea is that in order to grow the vector, it may not have enough free memory to expand into, and thus may have to move the whole array to some other location in memory, freeing the old block. That means in particular that your pointers now point to memory that has been freed, or reused for something else.
If you want to keep this approach, you will need to resize() or reserve() a sufficient number of elements in vec before starting. Which of course defeats the whole purpose of a std::vector, and you might as well use an array instead.
The vector is changing sizes and the addresses you are saving might not be those you want. You can preallocate memory using reserve() and the vector will not resize.
vec.reserve(3);
addRef(1);
addRef(2);
addRef(5);
The problem occurs when you call vec.push_back(n) and vec’s internal array is already full. When that happens, the std::vector::push_back() method allocates a larger array, copies the contents of the full array over to the new array, then frees the old/full array and keeps the new one.
Usually that’s all you need, but your program is keeping pointers to elements of the old array inside (rf), and these pointers all become dangling/invalid when the reallocation occurs, hence the funny (undefined) behavior.
An easy fix would be to call vec.reserve(100) (or similar) at the top of your program (so that no further reallocations are necessary). Or alternatively you could postpone the adding of pointers to (rf) until after you’ve finished adding all the values to (vec).
Just do not take pointer from a vector that may change soon. vector will copy the elements to a new space when it enlarges its capacity.
Use an array to store the ints instead.

Fast way to push_back a vector many times

I have identified a bottleneck in my c++ code, and my goal is to speed it up. I am moving items from one vector to another vector if a condition is true.
In python, the pythonic way of doing this would be to use a list comprehension:
my_vector = [x for x in data_vector if x > 1]
I have hacked a way to do this in C++, and it is working fine. However, I am calling this millions of times in a while-loop and it is slow. I do not understand much about memory allocation, but I assume that my problem has to do with allocating memory over-and-over again using push_back. Is there a way to allocate my memory differently to speed up this code? (I do not know how large my_vector should be until the for-loop has completed).
std::vector<float> data_vector;
// Put a bunch of floats into data_vector
std::vector<float> my_vector;
while (some_condition_is_true) {
my_vector.clear();
for (i = 0; i < data_vector.size(); i++) {
if (data_vector[i] > 1) {
my_vector.push_back(data_vector[i]);
}
}
// Use my_vector to render graphics on the GPU, but do not change the elements of my_vector
// Change the elements of data_vector, but not the size of data_vector
}
Use std::copy_if, and reserve data_vector.size() for my_vector initially (as this is the maximum possible number of elements for which your predicate could evaluate to true):
std::vector<int> my_vec;
my_vec.reserve(data_vec.size());
std::copy_if(data_vec.begin(), data_vec.end(), std::back_inserter(my_vec),
[](const auto& el) { return el > 1; });
Note that you could avoid the reserve call here if you expect that the number of times that your predicate evaluates to true will be much less than the size of the data_vector.
Though there are various great solutions posted by others for your query, it seems there is still no much explanation for the memory allocation, which you do not much understand, so I would like to share my knowledge about this topic with you. Hope this helps.
Firstly, in C++, there are several types of memory: stack, heap, data segment.
Stack is for local variables. There are some important features associated with it, for example, they will be automatically deallocated, operation on it is very fast, its size is OS-dependent and small such that storing some KB of data in the stack may cause an overflow of memory, et cetera.
Heap's memory can be accessed globally. As for its important features, we have, its size can be dynamically extended if needed and its size is larger(much larger than stack), operation on it is slower than stack, manual deallocation of memory is needed (in nowadays's OS, the memory will be automatically freed in the end of program), et cetera.
Data segment is for global and static variables. In fact, this piece of memory can be divided into even smaller parts, e.g. BBS.
In your case, vector is used. In fact, the elements of vector are stored into its internal dynamic array, that is an internal array with a dynamic array size. In the early C++, a dynamic array can be created on the stack memory, however, it is no longer that case. To create a dynamic array, ones have to create it on heap. Therefore, the elements of vector are stored in an internal dynamic array on heap. In fact, to dynamically increase the size of an array, a process namely memory reallocation is needed. However, if a vector user keeps enlarging his or her vector, then the overhead cost of reallocation cost will be high. To deal with it, a vector would firstly allocate a piece of memory that is larger than the current need, that is allocating memory for potential future use. Therefore, in your code, it is not that case that memory reallocation is performed every time push_back() is called. However, if the vector to be copied is quite large, the memory reserved for future use will be not enough. Then, memory allocation will occur. To tackle it, vector.reserve() may be used.
I am a newbie. Hopefully, I have not made any mistake in my sharing.
Hope this helps.
Run the code twice, first time only counting, how many new elements you will need. Then use reserve to already allocate all the memory you need.
while (some_condition_is_true) {
my_vector.clear();
int newLength = 0;
for (i = 0; i < data_vector.size(); i++) {
if (data_vector[i] > 1) {
newLength++;
my_vector.reserve(newLength);
for (i = 0; i < data_vector.size(); i++) {
if (data_vector[i] > 1) {
my_vector.push_back(data_vector[i]);
}
}
// Do stuff with my_vector and change data_vector
}
I doubt allocating my_vector is the problem, especially if the while loop is executed many times as the capacity of my_vector should quickly become sufficient.
But to be sure you can just reserve capacity in my_vector corresponding to the size of data_vector:
my_vector.reserve(data_vector.size());
while (some_condition_is_true) {
my_vector.clear();
for (auto value : data_vector) {
if (value > 1)
my_vector.push_back(value);
}
}
If you are on Linux you can reserve memory for my_vector to prevent std::vector reallocations which is bottleneck in your case. Note that reserve will not waste memory due to overcommit, so any rough upper estimate for reserve value will fit your needs. In your case the size of data_vector will be enough. This line of code before while loop should fix the bottleneck:
my_vector.reserve(data_vector.size());

Using the same vector without the resize() part

I have a question about std::vector -
vector<int> vec(1,0);
while(//something_1)
{
while(//something_2)
{
...
vec.pushback(var)
...
}
process(vec.size()); //every iteration- different size
vec.clear();
vec.resize(0,0);
}
On this case - every vec.push_back(var) there is reallocation of a new array with size bigger by one than the former array.
My question is - if there is a way using one vector, so after the inner while(//something_2), the vec.push_back(var) command will push back from the first cell of vec? instead of using vec.clear() and vec.resize(0,0)? so I could save the resize part and the reallocation.
The size of the vector is important for the function process(vec.size())
Thanks.
You can use reserve first time if you know beforehand approximately how much your vector could grow.
clear Leaves the capacity() of the vector unchanged. Which means that push_back & and other modifiers will use the same memory.
resize(0,0) should be removed.

C++: std::vector::reserve not reserving when containing pointers

When I call std::vector::reserve when the identifier is of type std::vector<Foo*> reserve(...) does nothing:
std::vector<int*> bar;
bar.reserve(20);
//I expect bar.size to return 20...
std::size_t sz = bar.size();
for(std::size_t i = 0; i < sz; ++i) {
//Do Stuff to all items!
}
The aforementioned for loop runs exactly zero times and bar.size() returns zero. I do not remember if this is also true for all other STL containers, but if so, including the behavior for std::vector: WHY?
.reserve() doesn't change the size of a vector. The member function you are looking for is .resize(). reserve() is simply an optimization. If you are going to add a bunch of things to a vector one-by-one using push_back() then telling it how many you will add using reserve() can make the code run a little bit faster. But just calling reserve() doesn't change the size.
vector::reserve() changes the capacity of a vector, not its size.
capacity is how much memory has been allocated internally to hold elements of the vector. size is how many elements have actually held by the vector. vector::resize() affects the latter.
reserve changes the capacity of the vector, not the size. You probably want resize

How to correctly deallocate or delete a c++ vector?

I have a weird problem with vector in C++..
I created a vector and inserted 10000 integer values into it and have checked the memory utilization. It is 600 kb. But after i erased the vector, still my system monitor says the program uses 600 kb.
Can anyone explain why the memory is not getting freed even after i erase the vector
Note: I have used all the methods for deletion(erase,pop_front,pop_back,clear...Even then I have the same problem)
Thanks and regards...:)
Presumably you checked memory with some system utility. Even if the vector space is freed on the heap that does not mean the heap space itself is going to be returned to the OS and reflected in the values shown in the system utility.
The only way to really get rid off unused memory in a std::vector<> pre C++11 is to swap it with an empty vector: vector<int>().swap(myvec). In C++11 you have a member function shrink_to_fit which often is implemented as the swap idiom just mentioned.
The C++ vector reserves more memory than it needs for its elements to speed up adding new elements and it doesn't free the reserved memory, after the elements have been deleted.
You can try swapping the vector with itself, to make the amount of reserved memory match the actual size of all the elements: v.swap(v)
Try deleting each element and then deleting the vector itself - see if that makes any difference.
Have you tried using valgrind to find out if there are any memory leaks?
Try using the erase-remove idiom. If you are just erasing all of the elements from the vector then all you are doing is moving the end() iterator. So everything is still there in the vector but "unavailable".
http://en.wikipedia.org/wiki/Erase-remove_idiom
The following code gives the answer:
#include <cstdio>
#include <vector>
struct Foo
{
~Foo()
{
printf("~Foo()\n");
}
};
int main()
{
std::vector<Foo> v;
v.push_back(Foo());
// This causes all Foo instances to be released as well as all
// space allocated by the vector to be released.
v = std::vector<Foo>();
// As you can see, all printf("~Foo()\n") calls happen before this
// line is printed.
printf("~~~~~~~~~~~~~~\n");
return 0;
}