What is the array form of 'delete'? - c++

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;

Related

Creating a global array of structs

For a project I am working on I need to have a global array of entry structs. I am having trouble though because I can't allocate memory until while running my program I determine the size of a file. The overall goal of this project is to create a word reference. So far how I am doing it is:
struct info{
//stores the specific character
std:: string c;
//stores the amount of times a word has come up in the file
float num;
}
info info_store[];
This project is to learn about arrays so I need to use an array
You can:
- use new/delete[]
info* p_array=new info[100]; // create an array of size 100
p_array[10].num; // member access example
delete[] p_array; // release memory
- use std::unique_ptr
std::unique_ptr<info[]> array(new info[size]);
-> The advantage is that your memory is automatically released when array is destroyed (no more delete[])
First of all, use std::vector or any other STL container.
Second, you can use dynamic arrays.
auto length = count_structs(file);
auto data = new info[length];
Something like this. Then just fill this array.
Ohh, and make sure you have delete [] data to prevent memory leaks.

How memory will be deleted?

Let's say I have structure
struct Foo {
int whatever;
int whatever2;
...
};
And I have this type of array
Foo **array = new Foo*[128];
Then, to every pointer I assign new structure
for (int i = 0; i < 128; i++)
array[i] = new Foo;
Then, after a while I deallocate:
delete[] array;
How memory will be deallocated?
Only the space for pointers will be freed
Space for pointer + the objects pointed by those pointers themselves?
Your code leaks memory. You need to call delete once for every new call (assuming the new doesn't fail and either return NULL or throw bad_alloc). So, in this case, you'll need to have a similar loop to the one that calls array[i] = new Foo; that does delete array[i];
I think this is one of points in Scott Meyers book, Effective C++ have read long back. But basic idea is, to avoid memory leak when you use new. make sure to call delete as many times as new is called and map new with delete and new[] with delete[] accordingly. so in your case new is called 128 times in for loop and new[] is called once, so similarly delete should be called same way to array[i] 128 times and delete[] should be called once for array. Hope this helps.

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.

Memory Leak, source: float** binsRowPtrs = new float *[_nbins];

How do I delete this properly?
float** binsRowPtrs = new float *[_nbins];
The items are not dynamic created with new.
float** binsRowPtrs = new float *[_nbins];
for (int i = 0; i < _nbins ;i++)
{
binsRowPtrs[i] = (float*) (bins[i].row(y).data);
}
How do i delete this properly[?]
Properly? You use RAII and let something else handle the deletion for you. Depending on what you're trying to do, you may want to use:
std::vector<std::vector<float>>: an array of arrays of floats;
std::vector<float*>: an array of non-owning pointers to floats (i.e. something else handles correct allocation and deallocation);
or maybe just std::vector<float>: an array of floats.
The rule is:
Call as many delete or delete[] respectively as new or new[] you used and on the exact same addresses.
So if you just called new on binRowPtrs then you just need to call delete binRowPtrs.
However, in the part of your code which you didn't show us, If you used dynamic allocation through new for each of the array elements then you need to loop through the array and call delete on each of the element as well.
Note that ideally,
In C++ You should use dynamic allocations only when you cannot avoid them &
If et all you must, never use raw pointers, always use RAII through smart pointers to avoid the explicit memory management(you already noticed the perils of doing so in your case).
This will clear those pointers:
delete [] binsRowPtrs;
But the actual data you are storing with bins won't be touched.

How to expand an array dynamically in C++? {like in vector }

Lets say, i have
int *p;
p = new int[5];
for(int i=0;i<5;i++)
*(p+i)=i;
Now I want to add a 6th element to the array. How do I do it?
You have to reallocate the array and copy the data:
int *p;
p = new int[5];
for(int i=0;i<5;i++)
*(p+i)=i;
// realloc
int* temp = new int[6];
std::copy(p, p + 5, temp); // Suggested by comments from Nick and Bojan
delete [] p;
p = temp;
You cannot. You must use a dynamic container, such as an STL vector, for this. Or else you can make another array that is larger, and then copy the data from your first array into it.
The reason is that an array represents a contiguous region in memory. For your example above, let us say that p points to address 0x1000, and the the five ints correspond to twenty bytes, so the array ends at the boundary of 0x1014. The compiler is free to place other variables in the memory starting at 0x1014; for example, int i might occupy 0x1014..0x1018. If you then extended the array so that it occupied four more bytes, what would happen?
If you allocate the initial buffer using malloc you can use realloc to resize the buffer. You shouldn't use realloc to resize a new-ed buffer.
int * array = (int*)malloc(sizeof(int) * arrayLength);
array = (int*)realloc(array, sizeof(int) * newLength);
However, this is a C-ish way to do things. You should consider using vector.
Why don't you look in the sources how vector does that? You can see the implementation of this mechanism right in the folder your C++ include files reside!
Here's what it does on gcc 4.3.2:
Allocate a new contiguous chunk of memory with use of the vector's allocator (you remember that vector is vector<Type, Allocator = new_allocator>?). The default allocator calls operator new() (not just new!) to allocate this chunk, letting himself thereby not to mess with new[]/delete[] stuff;
Copy the contents of the existing array to the newly allocated one;
Dispose previously aligned chunk with the allocator; the default one uses operator delete().
(Note, that if you're going to write your own vector, your size should increase "M times", not "by fixed amount". This will let you achieve amortized constant time. For example, if, upon each excession of the size limit, your vector grows twice, each element will be copied on average once.)
Same as others are saying, but if you're resizing the array often, one strategy is to resize the array each time by doubling the size. There's an expense to constantly creating new and destroying old, so the doubling theory tries to mitigate this problem by ensuring that there's sufficient room for future elements as well.