How can I delete a non-dynamically allocated array in C++? - 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.

Related

When should I use delete? (Consequences of not deleting after a dynamically created 2d array)

I am new to dynamic allocation and pointers. I will try to fill out a 2D dynamic array from a file and then apply a maze-solving algorithm (wall follower)on it.
Assuming I create a dynamically allocated 2D array like this:
int** board;
board = new int* [rowsize];
for(int row = 0; row < rowsize; row++)
{
board[row] = new int[colsize];
}
If I know that I won't be using this pointer for another variable, can I get away with not using delete for board ? If not what could potentially go wrong (If you are familiar with the wall follower algorithm) ? Also how do I delete a pointer to a pointer, would delete board be sufficient?
can I get away with not using delete for board?
Yes, but not for very long: repeated failure to delete arrays that your program allocates is a memory leak that eventually runs your process out of memory.
how do I delete a pointer to a pointer, would delete board be sufficient?
No, you will need to delete each pointer that you allocated and stored inside board:
for(int row = 0; row < rowsize; row++) {
delete[] board[row];
}
delete[] board;
Note square brackets after delete to indicate that you deleting an array, they are very important.
Allocating an deallocating memory for a rectangular matrix is a solved problem in C++ library. Switch to using a vector of vectors to avoid dynamic resource allocations:
std::vector<std::vector<int>> board(rowsize, std::vector<int>(colsize, 0));
If you don't delete the arrays you allocated they will continue to consume memory until the program is terminated. This might not technically be wrong, but it is wasteful.
With regard to deleting the board - no, it is not enough. You should delete every pointer you allocate with new:
for(int row = 0; row < rowsize; row++)
{
delete[] board[row];
}
delete[] board;
What you need to delete is the memory you allocated with new. That means that you don't deallocate the pointer itself, but the heap's memory it is pointing at.
So, you only need to do delete[] board. This will free up the int* array. It is not strictly necessary to use [] in this case, since it is a fundamental type array, but it is good practice to use it always for arrays, so you won't mess up when it's not like that.
Calling delete[] on an array will call the destructors of all objects inside the array itself, as well as freeing up the array. It is not necessary however for fundamental types.
Also note that you don't need to free the int** board. The pointer are variables like any other with some special capability, but they are allocated in the stack just like any other when you declare them like that.
Hope it helps :)

Vector of vector pointer memory allocation

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.

Why does calling 'delete' in a specific way on a dynamic array not work?

I'm wondering why this code doesn't work:
void KeyValueList::Release()
{
//(m_ppKeyValueList is a dynamic array of pointers to objects on the heap)
if (m_ppKeyValueList) {
for (int i = 0; i < m_iCapacity; ++i) {
if (m_ppKeyValueList[i]) {
delete m_ppKeyValueList[i];
}
}
/*delete[] m_ppKeyValueList;*/
for (int i = 0; i < m_iCapacity; ++i) {
delete (m_ppKeyValueList + i);
}
}
}
Why can't we iterate the dynamic array and delete it in this way?
A dynamic array is more than just a sequence of elements. It contains information about the array size as well. Moreover, there is just one chunk of memory known to the allocator. So just like with any dynamic memory, you can only free what you allocated, not smaller subsets of it.
That's why the language requires that you only invoke delete[] on a pointer obtained from a new[] expression, and that that is the only way to deallocate that memory.
Simple answer: because the language specifications say that you do that with a delete[].
Better answer: because after all for the heap manager the array pointed by m_ppKeyValueList is a single large allocation, not m_iCapacity consecutive small allocations, so you just have to tell it where the allocated block begins and it will deallocate it as a whole (after calling the single destructors if needed); if it kept each element as a single separated allocation into the allocated block lists it would be a stupid waste of resources (and if it used a bitmap for this it probably wouldn't have enough granularity to support this silly allocation scheme).
Because new int[5] allocates one contiguous block big enough to hold 5 ints. new int 5 times allocates 5 small blocks, each big enough to hold a single int. The number of deallocations must equal the number of allocations.
Case 1: m_ppKeyValueList is "a dynamic array of pointers to objects on the heap"
In this case you do need to delete m_ppKeyValueList piece by piece. If this is what you meant, your declaration will be of the form SomeType ** m_ppKeyValueList; Your allocation and deallocation should like
Allocation:
m_ppKeyValueList = new SomeType*[m_iCapacity];
for (int i = 0; i < m_iCapacity; ++i) {
m_ppKeyValueList[ii] = new SomeType;
}
Deallocation:
for (int i = 0; i < m_iCapacity; ++i) {
delete m_ppKeyValueList[ii];
}
delete[] m_ppKeyValueList;
However, that your code fails suggests that you do not have "a dynamic array of pointers to objects on the heap."
Case 2: m_ppKeyValueList is a dynamic array of objects on the heap
Here your declaration will be of the form SomeType * m_ppKeyValueList; Instead of allocating this piece by piece your allocation and deallocation take on a much simpler form:
Allocation:
m_ppKeyValueList = new SomeType[m_iCapacity];
Deallocation:
delete[] m_ppKeyValueList;
Bottom line:
Your allocations and deallocations need to match one another in number and in form. If you allocate something with new you need to destroy it with delete. If you allocate it with new[] you need to destroy it with delete[].

C++: Array with custom size in class

I want to do this:
class Graphic
{
int *array;
Graphic( int size )
{
int temp_array[size];
array = temp_array;
glGenTextures( size, array );
}
}
Will this work? And even if it will, is there a better way to do this?
Thanks.
Using new means you have to remember to delete [] it; using compiler-dependent variable-size arrays means you lose portability.
It's much better to use a vector.
#include <vector>
class Graphic
{
std::vector<int> array;
Graphic( int size )
{
array.resize(size);
glGenTextures( size, &array[0] );
}
}
The language guarantees that vector elements will be contiguous in memory so it's safe to do &array[0] here.
No, the memory for temp_array is allocated on the stack. When the function ends then that memory is deallocated and all you'll be left with is a dangling pointer. If you want to keep the array valid beyond the point that the constructor returns then allocate it dynamically using new. Example:
array = new int[size]
And then remember to delete it. Typically this is done in the destructor like this:
delete[] array

What is the array form of 'delete'?

When I compiled a code using the array name as a pointer, and I deleted the array name using delete, I got a warning about deleting an array without using the array form (I don't remember the exact wording).
The basic code was:
int data[5];
delete data;
So, what's the array form of delete?
The array form of delete is:
delete [] data;
Edit: But as others have pointed out, you shouldn't be calling delete for data defined like this:
int data[5];
You should only call it when you allocate the memory using new like this:
int *data = new int[5];
You either want:
int *data = new int[5];
... // time passes, stuff happens to data[]
delete[] data;
or
int data[5];
... // time passes, stuff happens to data[]
// note no delete of data
The genera rule is: only apply delete to memory that came from new. If the array form of new was used, then you must use the array form of delete to match. If placement new was used, then you either never call delete at all, or use a matching placement delete.
Since the variable int data[5] is a statically allocated array, it cannot be passed to any form of the delete operator.
As the other have said, you must use the vector form of delete:
void some_func(size_t n)
{
int* data = new int[n];
. . . // do stuff with the array
delete [] data; // Explicitly free memory
}
Be very wary of this, because some compilers will not warn you.
Even better, there is very rarely any need for using vector new/delete. Consider whether your code can be altered to make use of std::vector:
void some_func(size_t n)
{
std::vector<int> data(n);
. . . // do stuff with the array
} // memory held by data will be freed here automatically
And if you are dealing with the memory in a local scope, consider using STLSoft's auto_buffer, which will allocate from an internal buffer (held on the stack, as part of the instance) if possible, only going to the heap if it cannot:
void some_func(size_t n)
{
stlsoft::auto_buffer<int, 10> data(n); // only allocates if n > 10
. . . // do stuff with the array
} // memory held by data will be freed here automatically, if any was allocated
Read more about auto_buffer.
The code as shown has the array either on the stack, or in initialized part of the data segment, i.e. you don't deallocate it (which, as mentioned by others, would be "undefined behavior".) Were it on the "free store", you'd do that with delete [] data.
Just as RichieHindle stated above when you want to free the space dynamically allocated for an array pointed by data you have to put two brackets [] between the reserved word delete and the pointer to the beginning of the allocated space. Since data can point to a single int in memory as well as to the first element in the array this is the only way you let the compiler know that you want to delete the whole chunk of memory. If you don't do it the proper way the behaviour is "undetermined" (Stroustrup, The C++ Programming Language).
Fixes C4154 and C4156 warnings
float AR[5] = { 1.0f, 2.0f, ..., ..., ...};
delete [] & AR;