Vector of vector pointer memory allocation - c++

First I want to say that, I have a vector which has thousand of vectors inside. Each of these inside vectors has thousand of numbers inside. I want to keep memory management safe and memory usage at minimum as much as possible.
I want to ask that if I have a code similiar to below
int size = 10;
vector<vector<double>>* something = new vector<vector<double>>(size);
vector<double>* insideOfSomething;
for(int i = 0; i < size; i++){
insideOfSomething = &(something->at(i));
//...
//do something with insideOfSomething
//...
}
I know that 'something' will be created in heap. What I don't understand is where the vectors are placed, 'insideOfSomething' points? If they are created in stack, then this means that I have a vector pointer, which points a vector in heap, that has vectors inside which are created in stack? (I'm very confused right now.)
If I have a code similiar to the one below;
vector<vector<double>*>* something = new vector<vector<double>*>(size);
vector<double>* insideOfSomething;
for(int i = 0; i < size; i++){
something->at(i) = new vector<double>();
insideOfSomething = something->at(i);
//...
//do something with inside insideOfSomething
//...
}
right know all of my vectors are stored in heap, right?
Which one is more usefull according to the memory management?

You should avoid allocating vectors on the heap and just declare them on the stack since the vector will manage its objects on the heap for you. Anywhere you want to avoid creating a copy you can just use a reference or const reference (which ever is necessary).
vector<vector<double> > something(size);
for(int i = 0; i < size; i++)
{
vector<double> &insideOfSomething = something.at(i);
//use insideOfSomething
}

Let's take a random, simplistic implementation of vector, as I think this will help you.
template <class T, class Alloc>
class vector
{
private:
T* buffer;
std::size_t vector_size;
std::size_t vector_capacity
Alloc alloc;
public:
...
};
In this case, if we write:
vector<int> v;
v.push_back(123);
... the pointer, buffer, the integrals: vector_size and vector_capacity, and the allocator object, alloc, will all be created on the stack (along with allocating any additional memory necessary for structure padding and alignment).
However, vector itself will allocate memory on the heap to which this buffer pointer will store its base address. That will always be on the heap and will contain the actual contents of the vector as we think of them.
This is still more efficient than this:
vector<int>* v = new vector<int>;
v->push_back(123);
...
delete v;
... as this would involve a heap allocation/deallocation for the vector itself (including its data members) in addition to the memory vector itself allocates for its internal contents (the buffer). It also introduces an additional level of indirection.
Now if we have a vector of Somethings (vector of vector or anything else):
vector<Something> v;
Those Something instances are always going to be allocated within a contiguous heap buffer since they would reside in the dynamically allocated memory blocks that vector creates and destroys internally.

In vector<> all data stored in heap
And i think you should simply use
vector< vector<double> > something;

I want to keep memory management safe and memory usage at minimum as much as possible.
Then
vector<vector<double>>* something = new vector<vector<double>>(size);
is already not good. As said in the other answers, vector already has its data on the heap, no need to mess around with new to achieve this. In fact, the objects' location is like
S t a c k H e a p
(vector<double>) sthng[0]
(vector<vector<double>>) sthng (vector<double>) sthng[1]
...
- - - - - -
(double) sthng[0][0]
(double) sthng[0][1]
...
- - - - - -
(double) sthng[1][0]
(double) sthng[1][1]
...
(of course, there is no particular ordering of the blocks on the heap)

Joe and hired777's answers explain that a vector will be allocated on the heap no matter what. I'll try to give some insight on the reason for this.
A vector is a resizeable container. Generally it doubles in size when it reaches capacity which means it needs to be able to allocate more memory than it had already allocated. Hence even when you declare vector inside a function and hence on the stack, internally it's holding a pointer to it's data on the heap and on going out of the function's scope, it's destructor will delete this data from the heap.

Related

Delete a vector without deleting the array

I'm trying to populate a vector of doubles in C++ and pass the associated array to Fortran. But I'm having trouble freeing the rest of the memory associated with the vector. I'd like to avoid copying. Here's what I have:
std::vector<double> *vec = new std::vector<double>();
(*vec).push_back(1.0);
(*vec).push_back(2.0);
*arr = (*vec).data(); //arr goes to Fortran
How do I delete vec while keeping arr intact? Is there a way to nullify the pointer to arr in vec so that I can then delete vec?
Update
I see that I didn't give enough information here. A couple things:
I'm actually calling a C++ function in Fortran using iso_c_binding
I don't know how large the vec needs to be. The vector class looks good for this situation
I might try Guillaume's suggestion eventually, but for now, I'm passing vec to the Fortran and calling another C++ function to delete it once I'm done with the data
You need to rethink your program design.
Somehow, somewhere, you need to keep an array alive while Fortran is using it. So whatever context you're using to access Fortran should probably be responsible for ownership of this array.
class fortran_context {
/*Blah blah blah whatever API you're using to access Fortran*/
void * arr;
std::vector<double> vec; //Don't allocate this as a pointer; makes no sense!
public:
fortran_context() {
arr = //Do whatever is necessary to setup Fortran stuff. I'm assuming your
//api has some kind of "get_array_pointer" function that you'll use.
}
~fortran_context() {
//Do the cleanup for the fortran stuff
}
//If you want to spend time figuring out a robust copy constructor, you may.
//Personally, I suspect it's better to just delete it, and make this object non-copyable.
fortran_context(fortran_context const&) = delete;
std::vector<double> & get_vector() {
return vec;
}
std::vector<double> const& get_vector() const {
return vec;
}
void assign_vector_to_array() {
*arr = vec.data();
}
void do_stuff_with_fortran() {
assign_vector_to_array();
//???
}
};
int main() {
fortran_context context;
auto & vec = context.get_vector();
vec.push_back(1.0);
vec.push_back(2.0);
context.do_stuff_with_fortran();
return 0;
} //Cleanup happens automatically due to correct implementation of ~fortran_context()
I've abstracted a lot of this because I don't know what API you're using to access Fortran, and I don't know what kind of work you're doing with this array. But this is, by far, the safest way to ensure that
The vector's allocated memory exists so long as you are doing stuff in Fortran
The memory associated with the vector will be cleaned up properly when you're done.
How do I delete vec while keeping arr intact? Is there a way to nullify the pointer to arr in vec so that I can then delete vec?
The library does not provide any built-in capability to do that. You have to do the bookkeeping work yourself.
Allocate memory for the data and copy data from the vector.
Send the data to FORTRAN.
Decide when it is safe to deallocate the data and then delete them.
// Fill up data in vec
std::vector<double> vec;
vec.push_back(1.0);
vec.push_back(2.0);
// Allocate memory for arr and copy the data from vec
double* arr = new double[vec.size()];
std::copy(vec.begin(), vec.end(), arr);
// use arr
// delete arr
delete [] arr;
What you are asking for is not possible. std::vector, being a well behaved template class will release the internals that it owns and manages when it is destroyed.
You will have to keep vector alive while you are using its contents, which makes perfect sense. Otherwise, you will have to make a copy.
Also, I don't see why you are allocating the vector on the heap, it doesn't seem needed at all.
How do I delete vec while keeping arr intact? Is there a way to nullify the pointer to arr in vec so that I can then delete vec?
You don't.
I think you misuse or misunderstood what vector is for. It is not meant to expose memory management of the underlying array, but to represent a dynamically sized array as a regular type.
If you need to explicitly manage memory, I'd suggest you to use std::unique_ptr<T[]>. Since unique pointers offers a way to manage memory and to release it's resource without deleting it, I think it's a good candidate to meet your needs.
auto arr = std::make_unique<double[]>(2);
arr[0] = 1.;
arr[1] = 2.;
auto data = arr.release();
// You have to manage `data` memory manually,
// since the unique pointer released it's resource.
// arr is null here
// data is a pointer to an array, must be deleted manually later.
delete[] data;

c++ freeing memory in priority_queue

I have a
priority_queue<node*, std::vector<node*>, CompareNodes> heap;
Let's say the node consists of:
class node {
public:
int value;
int key;
int order = 1000000;
};
How do I free the memory after i'm done with the priority queue?
My approach doesn't seem to be working:
while (heap.top()) {
node * t = heap.top();
heap.pop();
delete t;
}
Looks like you'll want to do something more like this:
while (!heap.empty())
{ /* the rest ... */ }
If the heap is empty, .top() will throw an exception because there's nothing to return, which will happen when you are popping elements.
Also, if available you should use
priority_queue<std::unique_ptr<node>, std::vector<std::unique_ptr<node>>, CompareNodes> heap;
so you don't have to worry about clearing the memory yourself.
Just like most std:: containers, the memory may or may not be freed when you want it to be. Memory is usually kept around for a longer time so that when you perform a heap.push or equivalent operation, the memory doesn't need to be allocated again.
Think of std::vector which has to allocate a new set of memory for the entire vector each time it grows (vector data must be contiguous in memory). It is more efficient for std::vector to perform a large one time allocation and keep the memory around so that the growth operation doesn't kill performance -- a) allocate new space big enough, b) copy entire contents of existing vector to new vector space, c) delete the old vector space.
Bottom line is you can't force it to free memory for individual items.

Delete, Free, or Deallocate?

I'm running into a problem where I use too much memory on the stack. I'm using several large arrays that I only need between steps in my code. Basically I need to know how to release the memory used by an array variable that's created as:
float arrayName[length][width];
To intentionally release some auto storage (items on the 'stack'), you can do the following - basically you simply limit the scope of your variables
change code from:
//...
float arrayName[length][width];
// ...
change code to:
//...
{
float arrayName[length][width];
// use arrayName here
//... still in-scope
} // scope limit
// all of arrayName released from stack
{
// stack is available for other use, so try
uint32_t u32[3][length][width];
// use u32 here
//... still in-scope
} // scope ended
// all of u32 released from stack
// better yet, use std::vector or another container
std::vector<uint32_t> bigArry;
NOTE: a vector uses a finite amount of stack (24 bytes on my system),
regardless of how many elements you put into it!
You should use vectors for things like this. It is a part of the C++ standard library and is very optimized in most implementations. The memory taken up by the vector will automatically get released when the vector goes out of scope. So you will never have to free up the memory yourself.
Another benefit with using a vector is that you do not have to worry about running out of stack space since all the "array" memory taken up by the vector is located on the heap of the program.
For examples http://en.cppreference.com/w/cpp/container/vector/vector
Other than that if you think your program memory is never going to be enough then you should consider using the disk as another storage mechanism. Databases work this way. They store most of their data on disk.
You won't need any special statements.
The array will be released on function return or exiting the scope if it is local variable having automatic storage duration, or on exiting the program if it is static variable (declared outside functions).
You may want to allocate the memory on the heap if you are running into a situation where you are running out of memory on the stack. In this case you'll want to new up the array.
float** my_array = new float* [rowCount];
for(int i = 0; i < rowCount; ++i)
{
my_array[i] = new float[columnCount];
}
// and delete it later
for(int i = 0; i < rowCount; ++i)
{
delete [] my_array[i];
}
delete [] my_array;

How can I allocate memory for the std::vector<std::vector<int> > data type?

Suppose the following data structure typedef std::vector<std::vector<int> > MYARRAY is defined. Then for the variable MYARRAY var, how can I allocate memory for this variable before pushing data in it. For example,
std::vector<int> p1;
p1.push_back(1);
p1.push_back(2);
std::vector<int> p2;
p2.push_back(22);
p2.push_back(33);
var.push_back(p1);
var.push_back(p2);
If we do not allocate memory for var, then it will allocate memory automatically. So how can I allocate memory for this var before pushing data insider it? If it is std::vector<int> var2, I can just use var2.reserve(n) to allocate memory before using it.
EDIT:
Two suggestions have been made, but neither can work:
Solution 1: allocate memory for each element
var.reserve(3);
for(int i=0; i<3; i++)
var[i].reserve[20];
I use VC 2010 to compile and run the codes in the debug mode, and the following error message is given:
Solution 2: create the object in the beginning
std::vector<std::vector<int> > var(3, std::vector<int>(5));
After you created this variable, you can see this variable in VC 2010:
Its contents are already there. Therefore, if you push data on this variable, it will allocate memory once again.
EDIT 2:
Someone is interested in why I need allocate memory before using this variable, and the main reason is because of run-time library of windows. The variable var is defined in a executable program as an empty variable, and its contents are given by a function defined in a dynamic library. If both are using dynamic run-time library, it will not be an issue. But in my case both are linked with static run-time library, which means that each module is in charge of its memory allocation. Since var is defined in the executable program, it also should take care of its memory allocation.
The way you reserve memory for a vector is independent of what type the vector contains. If you want to reserve space for n elements in MYARRAY, call MYARRAY.reserve(n);.
Its contents are already there. Therefore, if you push data on this variable, it will allocate memory once again.
Right. Do you want to reserve memory or not? If you want to reserve memory, you'll have to use the memory you reserved. In order for you to "push data on this variable", you'd have to have the data somewhere, somewhere other than the memory you reserved. If you reserve memory and use that memory, you'll never have anything to push, because that would imply that you have something someplace other than in the memory you reserved that you need to add to the vector, which you couldn't possibly have.
You basically have three choices:
1) Don't reserve memory. Assemble the objects wherever you want and then push them into the vector. vec.push_back(myVector);
2) Reserve memory. Assemble the objects in place in the vector. vec[n].push_back(myInt);
3) Reserve memory. Assemble the objects wherever you want and then assign them into the memory you reserved. vec[n]=myIntVector
Notice that in none of these cases do you reserve memory and then push into the vector.
Like you already pointed out, std::vector has the reserve method that will reserve space for more data items. If you were to do p1.reserve(3) the vector would attempt to allocate space for 3 integers. If you run var.reserve(3), var will attempt to allocate space for 3 std::vector<int>'s, which is what it sounds like you want to do.
To allocate for the std::vector's inside of var, you could do:
for(int x=0; x<var.size(); x++) var[x].reserve(n);
EDIT
If you want to allocate space before inserting the vectors, you can declare var as:
std::vector<std::vector<int> > var(VEC_COUNT, std::vector<int>(n));
And then copy the new vectors in.
You cannot reserve space for vector's data before the vector exists. I believe you're looking for this:
void reserve(MYARRAY &arr, size_t dim1, size_t dim2)
{
arr.resize(dim1);
for (size_t idx = 0; idx < dim1; ++idx) {
arr[idx].reserve(dim2);
}
}

How can I delete a non-dynamically allocated array in C++?

The reason why I ask is because I am using a non-dynamically allocated array for my hashtable; however, for my rehash function in my hashtable, I need to be able to change the size of my old array. How can I do this?
If you want to change the size, you have to allocate it dynamically, preferably using std::vector.
Short answer: you can't.
A longer answer would introduce very dirty and os-dependent hacks.
If you want to manually control the lifetime of memory, you need to use dynamic memory allocation. Non-dynamically allocated memory (statically allocated) will only be deallocated when the memory goes out of scope. Since this memory lives in the object your managing, that memory only goes out of scope when the owning object in deallocated.
So you will need to dynamically allocate a buffer at construction then when resizing allocate a new buffer, copy the contents from the old buffer into the new buffer, delete the old buffer, then assign your object's internal pointer to the new buffer. Something like:
// allocate a new, bigger array
Cell* newBuff = new Cells[/*newSize*/];
// copy into the new array
for (i = 0; i < myBufferSize; ++i)
{
newBuff[i] = myBuffer[i];
}
// delete the old array
delete myBuffer;
// point to the new array
myBuffer = newBuff;
Could you base your hash table on a std::vector instead of using manual memory allocation? This will handle the dynamic array for you, and you can resize with a simple .resize:
myBuffer.resize(/*newSize*/)
There are dozens of ways to handle this out. Of course "deallocating" a memory that was not allocated on the heap - is the worst hack to imagine.
I may suggest something like this:
class MyClass
{
TableEntry* m_pStaticTable[/* some size */];
TableEntry* m_pActualTable;
size_t m_nSize;
MyClass()
:m_pActualTable(m_pStaticTable)
,m_nSize(_countof(m_pStaticTable))
{
}
~MyClass()
{
if (m_pActualTable != m_pStaticTable)
delete[] m_pActualTable;
}
};
Assuming you have something like this:
TableEntry table[max_table_size];
you are going to need a separate variable that indicates how much of the array you are actually using:
size_t table_size = 0;
and then you just use that variable instead of trying to resize the actual array.