How to remove elements from dynamically allocated array? - c++

I have a dynamically allocated array :
myRectangle lastRectanglesArray = new myRectangle[lastMaxLabel];
I would like to loop through all elements in this array and remove these that will meet my condition (e.g. too big rectangle).
I have been thinking that I can loop through this array and get the number of elements that would satisfy my condition and then allocate a new array. But how can I 'transfer' these 'wanted' elements into my new array ?
Just for the record: I cannot use STL containers.

myRectangle * lastRectanglesArray = new myRectangle[lastMaxLabel];
// initialize the entries in the lastRectanglesArray
// create a temporary array which contains info about each individual
// entry. namely, it only holds info about whether the entry should
// be kept, or deleted.
// we also use the 'entries' value, which is the number of entries
// in the new array
bool * entriesToKeep = new bool[lastMaxLabel];
int entries = 0;
// check each entry, and mark whether it should be kept or deleted
for (int i = 0; i != lastMaxLabel; ++i) {
// check whether the entry should be kept or deleted...
// here, i just put a function with signature like:
// bool shouldKeepRectangle(const myRectangle &);
entriesToKeep[i] = shouldKeepRectangle(lastRectanglesArray[i]);
if (entriesToKeep[i]) ++entries;
}
// create a new array that will contain the entries that should be kept
myRectangle * rectanglesArray = new myRectangle[entries];
// assign the entries in the new array
for (int i = 0, j = 0; i != lastMaxLabel && j != entries; ++i) {
if (entriesToKeep[i])
rectanglesArray[j++] = lastRectanglesArray[i];
}
// free the memory held by the temp array
delete [] entriesToKeep;
// if the old array is not needed anymore, delete it
delete [] lastRectanglesArray;
// and here you have rectanglesArray, a brand new array that contains
// only the elements that you need.

Just move the next array location over the one that needs to be deleted, and shift everything over til the end of the array.

Yours look like the perfect case for using a Linked List. You would however have to do away with the new myRectangle[lastMaxLabel] part as you would have to implement it as pert of your Insert() function.
This way you would not require to transfer the wanted elements into a new array, but just delete the unwanted element.
Any more light on your use-case would help us to think of better alternatives.

I agree with Michael Chinen - use std::vector instead. You'll avoid lots of other potential problems this way. If you really want to use dynamic arrays, see this question: Remove an array element and shift the remaining ones

if you have a big amount of data in array that will be a problem for shifting using loop
maybe you should build your own array management class (find,add,deleteAt,etc).
my suggestion use link list node method.. it will be faster rather then you use loop for shifting.

Related

Dynamic array seems bigger than the dynamic size variable for it

I have class A, in it I have a dynamic array arr and a dynamic variable s which determines the size of the array. At the start of my main I use the constructor for class A which sets s to 2 and fills the arr with dummy objects. Now when I add objects to the array and sort it, objects seem to disappear.
The size of my array (so variable s) gets doubled when there is not enough space in the array, so no free slot available.
The way I display the array is by using a for loop with the limit i < s. So it should display all objects in the array.
Now when I add more objects and the array gets bigger, the previously "lost" objects start to appear again. So it seems like my array is bigger than the variable s, which dynamically determines the size.
How is that possible?
class A
private:
int *s = new int;
obj *arr = new obj[*s];
//triggers when trying to add an object to the array, but every place from
//arr[0] to arr[s-1] is taken by non dummy object
void A::resize {
*s *= 2;
//for loop that fills code with dummy objects
}
void A::display {
for (int i = 0; i < *s; i++) {
displayobject(i);
}
}
I had a very similar code last year in university and everything worked fine, can't find my mistake.
I would just use a vector, where i can easily use a for loop to go through the real size, but our prof wants us to use a dynamically alocated array.

Decrease array size after deletion of random item but keep the rest intact

Let's say we have an array of data and we do some stuff with the data.
At some point 1 of those data will be deleted for good, never to be seen again.
How do I remake the array again in a way that the item that I want to be deleted is gone and the rest of the array remains intact but with reduced size?
People are flagging me for duplicates, but it's not. I can't use vectors, because I have to make it work with arrays.
A way to do this is to create an array list.
int elements = 10;
int *arrayList= new int [elements]; //create first arraylist of size 10
int *arr2= new int [elements/2]; //create 2nd arraylist of size 5
for(int i=0; i<arr2.length; i++)
arr2[i]=arrayList[i]; //fill in the 2nd array
I followed #crashmstr answer which was the closest to what I wanted to do!
std containers.
Copying the entire array except for the deleted element wont do in large files because it adds process time, cycles, cache misses etc...
Thanks!

C++ How to create a dynamic array of vectors?

I'm having problem initialising an array of std::vectors.
I'm declaring and initialising it like this:
vector<component_change*>* _changes;
_changes = new vector<component_change*> [numThreads];
in the hope that it's in the same form as this:
int * foo;
foo = new int [5];
but when I hit a breakpoint after the initialisation, _changes' size is 0.
What am I doing wrong and how can I fix it?
I don't want to use a vector of vectors as the number I need remains constant throughout the program but depends on the current hardware. And I'm not just looking for a single vector (Each vector will be used by a different thread then merged when the threads have finished their tasks).
Thanks guys! :)
Your program is correct. But you misinterpreted the debugger. _changes's size is not 0, but the first vector in your array (the one _changes points at) is empty. Thats because the debugger does not know if _changes points at a single element or an array (in that case the compiler would not know how many elements are in that array). Simply use a vector and call std::vector::shrink_to_fit.
If the size can be determined at compile time use a std::array. If the size is a run-time argument then use a vector and don't change the size of the container.
Are you interested in have a vector for each thread, or a vector containing items used by each thread? I assumed the later, but my answer could be adapted.
This is using a statically sized array; (this syntax is close).
const int NUMBER_OF_THREADS = 5;
component_change* _changes[NUMBER_OF_THREADS] =
{
new component_change(1),
new component_change(2),
new component_change(3),
new component_change(4),
new component_change(5)
}
If the number of threads is dynamic, you will have to use a new...
int NUMBER_OF_THREADS = system.getThreadCount();
component_change* _changes = new component_change[NUMBER_OF_THREADS];
for (int i = 0; i < NUMBER_OF_THREADS; i++)
{
_changes[i] = new component_change(i+1);
}
If you want to a std::vector:
int NUMBER_OF_THREADS = system.getThreadCount();
std::vector<component_change*> _changes;
_changes.reserve(NUMBER_OF_THREADS);
for (int i = 0; i < NUMBER_OF_THREADS; i++)
{
_changes.push_back(new component_change(i+1));
}
I think you're kind of mislead, this size that you are reading belongs to the vector in the first element of the array. Its size is equal to 0 since no elements have been inserted in the vector yet.
new vector is usually wrong.
You should use, with most preferred if possible first,
std::vector<component_change> _changes(numThreads);
or
std::vector<std::unique_ptr<component_change>> _changes(numThreads);
or
std::vector<component_change*> _changes(numThreads);
or if each element of the vector should itself contain an array of components (it's not clear in your question)
std::vector<std::vector<**component_change**>> _changes(numThreads);
Declaring the component as one of the above ways, depending on your needs.
Note that the pointers begin not pointing to anything. You'd have to allocate the individual components as a separate step.
The following creates an array of numThreads vectors, not a vector of numThread elements.
new vector<component_change*> [numThreads]

When allocating a dynamic array, are the previous elements deleted?

Title says it all more or less. When I need an (for the sake of this example) integer array for an unknown amount of values I know I can change it's size using new *array = new int[size]. Now my question is: If I have an array of a certain size, but I need to make it bigger, can I just use the new operator to expand it and will it still have all previously stored elements or would it be smarter to create a whole new array with a dynamic size, copy all elements from the previous array into the new one and delete[] the old array. Basically just swapping between the two arrays, whenever I need a new size.
Specifically I am asking whether or not this piece of code would work in the way it's intended to work
for(int i = 1; i < 10; i++){
int *array = new int[i];
array[i-1] = i;
}
My assumption is that this array will first be the size of 1 and store the value 1 at index 0. Then it will reallocate its size to 2 and store the value to at index 1 and so on until i is 9.
I guess to rephrase my question a bit better: Does an array initialized with new have to be populated with elements or will it copy the elements it had from before using the operator?
You can't resize the array in this way. You need to make a new array and then copy the old array into it. You can also try std::vector, which does what you want automatically.
If you want to use pointers rather than std::vector to change the size of your array, you can do it in this way.
int n = 100; // This will be the number of elements.
int *array1; // Pointer
array1 = new int[n]; // This will allocate your array with size n, so you will have 100 elements. You can combine this with the previous in int *array1 = new int[n];
So fill up the this array however you please...
Then you decide you want a 200 element array instead? You will need to create a different array in the same way.
int *array2 = new int[200];
You can use the for loop to copy array 1 into array 2. The for loop should iterate as many times as there are elements in array 1 (100).
for(int i = 0; i < 100; ++i)
array2[i] = array[1];
At this stage array2 is exactly the same as array1, but with 100 uninitialized elements at your disposal from [100] to [199].
You won't need array1 anymore, so at some point, you should call
delete [] array1;
Your assumption, by the way would not work, because on the first cycle of your loop, you create (or try to create) an array of i=1 element. Arrays start counting at 0, so your only single element is [0]. When i is at 0, what is i-1?
If you try to access array[-1], you'll probably crash. But why should you want to create 10 different arrays? new keyword creates an unrelated object, not overwrites the one with the same name.
Does an array initialized with new have to be populated with elements or will it copy the elements it had from before using the operator?
new[] allocates new array, completely independent from previous.
I know 3 ways to "make the array bigger":
As #ravi mentioned, don't mess with poinsters, use modern std::vector.
Make new array in new pointer, std::move elements from old array to the new one, and then delete[] old array.
Get rid of new[] & delete[], use old realloc with malloc & free.
You have to allocate new array and copy old array's data into that. This is how vector is implemented. Had there been better way of doing it, C++ standard community would have considered that.

dynamic allocation and deallocation

I am a bit confused here, suppose i am making a container that will hold some elements and those elements can be removed.
I would have a fixed array of elements for that.
Now my question is with allocating and deallocating that array and deallocatisingle elements in it.
1) Allocating
Item* data;
Container()
{
data = new Item[size];
}
Then to add I do something like that:
add(Item it)
{
data[empty++] = it;
}
Now my question is with that allocation I have created size objects of Items then when I come in the add I add another item above, so does this means there is destruction of the old and the new take over?
Should I better use allocater<T> and uninitializedfill() as I read it allocate required memory without constructing the object.
2) Deallocating:
Here comes all the confusion really , on removing a single element can I use that?
remove(Item it)
{
//index is item index
delete data[index];
//restore contiguity to array
empty--;
}
can I use delete data[index] even if Item isn't a pointer? if not how then could I do this part?!
If I can then, what if Item was a pointer so when I delete it does it deletes the object pointed by it?
When you allocate a fixed-length array with
data = new Item[size];
you have allocated all size elements of the array at once, in a contiguous block of memory. You do not allocate individual elements in the array, and you cannot deallocate individual elements with delete data[index] -- you can only deallocate the entire array with delete[] data when you are done.
If you anticipate needing to add and remove elements at the end of the array, I recommend using std::vector instead. If you expect to add and remove elements anywhere in the array, std::list probably makes more sense.
data = new Item[size];
This creates an array of Items of size length, and return a poitner to them. Those itemswill be in indexes 0..(size-1) inclusive.
data[empty++] = it;
Assuming empty is < size, this will bash one of your items over the head, repalcing it with the Item passed into add(). If empty >= size than bad things will happen.
delete data[index];
This is not legal code. You are stuck with all (size) Items until you want to delete the lot.
Use:
std::vector<Item> data(N);
You have to decide if Items are values or referred objects. In fact allocation and deallocation look incoherent:
new Item[size] actually creates size Items (that start to exist all together) and data[i] = item copies the lone item intio the ith Item addressed by data (replacing its internal value). In this way you are not "inserting" anything. the empty index (what a bad name...) just defines what to replace.
delete data[index] cannot work, because data[index] is not a pointer (its an Item itself).
The pair with data = new Item[x] is delete[] data that deletes all them together as together thay have been created.
Inserting and removing an item inside a block of Items of a given predefined size is ... nonsense (if you can do the the size is not predefined).
You have to consider reallocating the array, copy, and shifting elements. But this is nothing more than re-implementing std::vector.