I am trying to shrink an array of *bool but I am not sure if it is being deleted correctly.
This is my source code...
bool *oldStore;
void shrinkArray(int i)
{
int k;
bool *newStore;
for(k=0; k<i; k++)
{
newStore[k] = oldStore[k];
}
for(; k<originalSize; k++)
{
delete[] oldStore[k];
}
delete[] oldStore;
oldStore = newStore;
}
For example, if I wanted to shrink the array to 5 and the original size of the array was 15, it would keep the first five and delete the last ten, however I am not too sure if my memory is being managed correctly.
Think about you method design before going into the coding specifics. I assume you have an ínt array that you new somewhere in your code.
Think about who "owns" this array? It's probably no good idea to create the int array at some place and to simply delete[] it somewhere else. Check out the following links: What is a smart pointer and when should I use one?
Think about what should happen to your newStore array. Is it supposed to replace the oldStore or do you want both arrays to exist in parallel. If you simply put the newStore on the heap who/when and where are you going to delete[] it again.
Simplest code would be:-
void shrinkArray(int i)
{
int k;
bool *newStore = new bool[i];
for(k=0; k<i; k++)
{
newStore[k] = oldStore[k];
}
delete [] oldStore; //assuming oldstore was allocated using new []..
oldStore = newStore;
}
Your code is wrong. You declared pointer newStore but neither initialize it nor allocated memory that would be pointed to by this pointer
bool *newStore;
So the next loop has undefined behaviour.
for(k=0; k<i; k++)
{
newStore[k] = oldStore[k];
}
Moreover if each element of the array pointed to by pointer oldStore has type bool * that is in turn is a pointer then oldStore itself shall have type bool **
If so then the correct function could look like
void shrinkArray( int n )
{
if ( n < originalSize )
{
bool **newStore = new bool * [n];
int i = 0;
for ( ; i < n; i++ ) newStore[i] = oldStore[i];
for ( ; i < originalSize; i++ ) delete oldStore[i];
delete [] oldStore;
oldStore = newStore;
originalSize = n;
}
}
Take into account that oldStore also shall have type bool **.
Otherwise if each element of the original array has type bool then the code will look like
void shrinkArray( int n )
{
if ( n < originalSize )
{
bool *newStore = new bool [n];
int i = 0;
for ( ; i < n; i++ ) newStore[i] = oldStore[i];
// Or
// std::copy( oldStore, oldStore + n, newStore );
delete [] oldStore;
oldStore = newStore;
originalSize = n;
}
}
Take into account that it would be much better and simpler to use standard container std::vector<bool *> or std::vector<bool> depending on the type of the element of the container.
Related
I'm trying to delete my 2D array, but I consistently get errors when I try to delete it, we have to work backwards so I delete the elements first, then the column array, then the row array. here is my code for the constructor in my class, MyMatrix:
private:
int m; //rows
int **ptr; //ptr to first dimension
int n; // columns
public:
MyMatrix() //constructor
{
m = 0;
n = 0;
ptr = new int*[m];
int *length_arr = new int[m];
for (int i = 0; i <= m-1; i++)
{
*(ptr+i) = new int[n];
*(length_arr+i) = n;
}
}
and my destructor looks like this:
for(int i = 0; i <= m-1; i++)
{
for (int j = 0; j <= n-1; j++)
{
delete ((*(ptr+i))+j);
}
delete[] *(ptr+i);
}
delete[] ptr;
the error I'm getting is:
assg7(2677,0x100de3d40) malloc: *** error for object 0x12d606804: pointer being freed was not allocated
I've wracked my brain for where I can fix this, for context, I'm doing an assignment with operator overloading. I specifically need a delete function to work properly for my = assignment overloading since I want to delete and again reallocate memory to equate two matrices, but the terminal is showing malloc errors and is thus not equating the matrices.
for additional info here is my = overloading code:
void operator = (const MyMatrix &obj)
{
if(n == obj.n && m == obj.m)
{
//for loop to equate elements in this-> to the elements of the passed object
}
else
{
for(int i = 0; i <= m-1; i++)
{
for (int j = 0; j <= n-1; j++)
{
delete ((*(ptr+i))+j);
}
delete[] *(ptr+i);
}
delete[] ptr;
// the code for assigning new memory according to the passed objects rows and colums goes here
//then for loop to equate elements in this-> to the elements of the passed object
}
}
thanks.
You have two "levels" of new, so three "levels" of delete can't be right.
Spell out your deletion loop, using indexing instead of pointer arithmetic:
First iteration:
delete ptr[0]+0;
delete ptr[0]+1;
...
delete ptr[0]+n-1;
delete [] ptr[0];
Second iteration:
delete ptr[1]+0;
delete ptr[1]+1;
...
delete ptr[1]+n-1;
delete [] ptr[1];
You're passing to delete a pointer to the first element of ptr[0], a pointer to the second element of ptr[0], a pointer to the third element of ptr[0], ...
But the things you allocated were ptr[0], ptr[1], ... ptr[m-1], not their individual elements.
Remove the innermost deletion loop.
(And don't mess around with pointer arithmetic when you can use indexing.)
I don't know how you would want to allocate memory space by m length if it is set to 0 by default.
To me it looks like you set m = 0 and then try to allocate by 0 length or how do you control the length of your dimensions?
Maybe edit your constructor to:
MyMatrix(int m, int n)
{
this->m = m;
this->n = n;
...
In main I can:
Node* myNodeArray2[myHeight][myWidth];//Does not call constructor
for(int i=0; i<myHeight; i++){
for(int j=0; j<myWidth; j++){
theNodeArray[i][j] = new Node("ThisIsTest", 5, 5);
}
}
So for the above code myHeight and myWidth can be user input at run time. It does not call the default constructor and I can use the new operator and go through the array creating the objects.
I want to be able to pass Node* myNodeArray2 to a function and let it create the array size and populate it. When it is created I want the elements to be pointers. I don't want to call the default constructor. I want to be able to at my choosing call the new operator with the non-default constructor.
When I try:
void Test(Node*& theNodeArray, int myHeight, int myWidth){
theNodeArray = new Node*[myHeight][myWidth];
}
int main(){
Node* myNodeArray;
Test(myNodeArray, myHeight, myWidth);
}
I get that
"myWidth is not a constant expression."
I have tried a couple of different methods but cannot get what I want. I need the creation to happen in a separate function. I need to be able to define the size at runtime. Any help?
Edit:
I don't want to use std::vector.
Edit 2:
I don't want to do this
int** ary = new int*[sizeX];
for(int i = 0; i < sizeX; ++i)
ary[i] = new int[sizeY];
As this forces the rows to be of objects of contiguous memory space. I want to allocate a 2d array of pointers. I do not want to necessarily create the objects that will be pointed to.
You may use the following:
Node*** MakeArrayNodePtr(int myHeight, int myWidth){
Node*** res = new Node**[myHeight];
for (int i = 0; i != myHeight; ++i) {
res[i] = new Node*[myWidth]();
}
return res;
}
And don't forget
void DeleteArrayNodePtr(Node*** nodes, int myHeight, int myWidth)
{
for (int i = 0; i != myHeight; ++i) {
// And probably:
/*
for (int j = 0; j != myWidth; ++j) {
delete nodes[i][j];
}
*/
delete [] nodes[i];
}
delete [] nodes;
}
The following snippet of code is my attempt to increase the size of an array by a factor of two. I am having several problems with it. Most importantly, should I be calling delete on my original array?
void enlarge(int *array, int* dbl int size) {
for (int i = 0; i < size; i++)
dbl[i] = array[i];
delete array;
array = dbl;
}
You have a few problems:
Modifying array only modifies the local copy of the pointer. You need to take a reference-to-pointer if you want the modification to be observed by the calling code.
You need to use delete[] when deleting things allocated with new[].
You attempt to copy too many items, and in so doing you overrun the original array.
void enlarge(int *& array, int size) {
// ^
// Use a reference to a pointer.
int *dbl = new int[size*2];
for (int i = 0; i < size; i++) {
// ^
// Iterate up to size, not size*2.
dbl[i] = array[i];
}
delete[] array;
// ^
// Use delete[], not delete.
array = dbl;
}
However, I would strongly suggest using std::vector<int> instead; it will automatically resize as necessary and this is completely transparent to you.
keyword double cannot be used as variable name, and previous array must be deleted before new allocation get assigned to same pointer, and loop should copy size no of items from prev array (not 2 * size)
void enlarge(int **array, int size) {
int *d = new int[size*2];
for (int i = 0; i < size; i++)
d[i] = *array[i];
delete [] *array;
*array = d;
}
if previous array was int *arr, and size is the currentsize of the array arr, call should be as: enlarge(&arr, size)
Ok, so I'm quite new to C++ and I'm sure this question is already answered somewhere, and also is quite simple, but I can't seem to find the answer....
I have a custom array class, which I am using just as an exercise to try and get the hang of how things work which is defined as follows:
Header:
class Array {
private:
// Private variables
unsigned int mCapacity;
unsigned int mLength;
void **mData;
public:
// Public constructor/destructor
Array(unsigned int initialCapacity = 10);
// Public methods
void addObject(void *obj);
void removeObject(void *obj);
void *objectAtIndex(unsigned int index);
void *operator[](unsigned int index);
int indexOfObject(void *obj);
unsigned int getSize();
};
}
Implementation:
GG::Array::Array(unsigned int initialCapacity) : mCapacity(initialCapacity) {
// Allocate a buffer that is the required size
mData = new void*[initialCapacity];
// Set the length to 0
mLength = 0;
}
void GG::Array::addObject(void *obj) {
// Check if there is space for the new object on the end of the array
if (mLength == mCapacity) {
// There is not enough space so create a large array
unsigned int newCapacity = mCapacity + 10;
void **newArray = new void*[newCapacity];
mCapacity = newCapacity;
// Copy over the data from the old array
for (unsigned int i = 0; i < mLength; i++) {
newArray[i] = mData[i];
}
// Delete the old array
delete[] mData;
// Set the new array as mData
mData = newArray;
}
// Now insert the object at the end of the array
mData[mLength] = obj;
mLength++;
}
void GG::Array::removeObject(void *obj) {
// Attempt to find the object in the array
int index = this->indexOfObject(obj);
if (index >= 0) {
// Remove the object
mData[index] = nullptr;
// Move any object after it down in the array
for (unsigned int i = index + 1; i < mLength; i++) {
mData[i - 1] = mData[i];
}
// Decrement the length of the array
mLength--;
}
}
void *GG::Array::objectAtIndex(unsigned int index) {
if (index < mLength) return mData[index];
return nullptr;
}
void *GG::Array::operator[](unsigned int index) {
return this->objectAtIndex(index);
}
int GG::Array::indexOfObject(void *obj) {
// Iterate through the array and try to find the object
for (int i = 0; i < mLength; i++) {
if (mData[i] == obj) return i;
}
return -1;
}
unsigned int GG::Array::getSize() {
return mLength;
}
I'm trying to create an array of pointers to integers, a simplified version of this is as follows:
Array array = Array();
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject(&j);
}
Now the problem is that the same pointer is used for j in every iteration. So after the loop:
array[0] == array[1] == array[2];
I'm sure that this is expected behaviour, but it isn't quite what I want to happen, I want an array of different pointers to different ints. If anyone could point me in the right direction here it would be greatly appreciated! :) (I'm clearly misunderstanding how to use pointers!)
P.s. Thanks everyone for your responses. I have accepted the one that solved the problem that I was having!
I'm guessing you mean:
array[i] = &j;
In which case you're storing a pointer to a temporary. On each loop repitition j is allocated in the stack address on the stack, so &j yeilds the same value. Even if you were getting back different addresses your code would cause problems down the line as you're storing a pointer to a temporary.
Also, why use a void* array. If you actually just want 3 unique integers then just do:
std::vector<int> array(3);
It's much more C++'esque and removes all manner of bugs.
First of all this does not allocate an array of pointers to int
void *array = new void*[2];
It allocates an array of pointers to void.
You may not dereference a pointer to void as type void is incomplete type, It has an empty set of values. So this code is invalid
array[i] = *j;
And moreover instead of *j shall be &j Though in this case pointers have invalid values because would point memory that was destroyed because j is a local variable.
The loop is also wrong. Instead of
for (int i = 0; i < 3; i++) {
there should be
for (int i = 0; i < 2; i++) {
What you want is the following
int **array = new int *[2];
for ( int i = 0; i < 2; i++ )
{
int j = i + 1;
array[i] = new int( j );
}
And you can output objects it points to
for ( int i = 0; i < 2; i++ )
{
std::cout << *array[i] << std::endl;
}
To delete the pointers you can use the following code snippet
for ( int i = 0; i < 2; i++ )
{
delete array[i];
}
delete []array;
EDIT: As you changed your original post then I also will append in turn my post.
Instead of
Array array = Array();
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject(&j);
}
there should be
Array array;
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject( new int( j ) );
}
Take into account that either you should define copy/move constructors and assignment operators or define them as deleted.
There are lots of problems with this code.
The declaration void* array = new void*[2] creates an array of 2 pointers-to-pointer-to-void, indexed 0 and 1. You then try to write into elements 0, 1 and 2. This is undefined behaviour
You almost certainly don't want a void pointer to an array of pointer-to-pointer-to-void. If you really want an array of pointer-to-integer, then you want int** array = new int*[2];. Or probably just int *array[2]; unless you really need the array on the heap.
j is the probably in the same place each time through the loop - it will likely be allocated in the same place on the stack - so &j is the same address each time. In any case, j will go out of scope when the loop's finished, and the address(es) will be invalid.
What are you actually trying to do? There may well be a better way.
if you simply do
int *array[10];
your array variable can decay to a pointer to the first element of the list, you can reference the i-th integer pointer just by doing:
int *myPtr = *(array + i);
which is in fact just another way to write the more common form:
int *myPtr = array[i];
void* is not the same as int*. void* represent a void pointer which is a pointer to a specific memory area without any additional interpretation or assuption about the data you are referencing to
There are some problems:
1) void *array = new void*[2]; is wrong because you want an array of pointers: void *array[2];
2)for (int i = 0; i < 3; i++) { : is wrong because your array is from 0 to 1;
3)int j = i + 1; array[i] = *j; j is an automatic variable, and the content is destroyed at each iteration. This is why you got always the same address. And also, to take the address of a variable you need to use &
I have problems deleting an array
int calc_mode (vector<int> array, int arrSize) {
int ipRepetition = new int[arrSize];
int j;
bool bFound;
for(int i =0; i<arrSize; i++) {
ipRepetition [i] = 0;
j=0;
bFound = false;
while ( j<i && array[i] != array[j] ) {
if(array[i] != array[j]) {
++j;
}
}
}
int iMaxRepeat = 0;
for(int i =0; i<arrSize; i++) {
if(ipRepetition[i] > ipRepetition[iMaxRepeat] ) {
iMaxRepeat = i;
}
}
delete [] ipRepetition; //compiler is complaining here
return array[iMaxRepeat];
}
Error : Cannot delete 'ipRepetition' ....Can you please point out what I missed?
Sometimes the best answer is to unask the question. Instead of hand-allocating that array of int, use another vector<int>.
int ipRepetition = new int[arrSize];
It's not correct. ipRepetition must be pointer.
int* ipRepetition = new int[arrSize];
You need an int* instead of an int.
int* ipRepetition = new int[arrSize];
Along with #Pete Becker's (IMO, excellent) suggestion, I'd consider using some standard algorithms to do most of the work. std::mismatch can tell you each location where a run ends (i.e., where a value in the input is not equal to the previous value). Along with std::distance (or just subtraction, since you're using random access iterators) that will tell you the length of each run fairly directly.
Once you've found the run lengths, you can use std::max_element to find the longest of them.