I've seen bunch of tutorials and threads, but no-one does this to resize an array. My question is, whether this affects bad something in my program or is there better way to resize it?
//GOAL:Array to become {1,2,4,5,6,7,8,9}
int size=9;
int array[size] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for (int i = 2; i < 8; ++i)
array[i] = array[i + 1];
//ARRAY IS NOW{1, 2, 4, 5, 6, 7, 8, 9, 9}
//GOAL: TO DELETE THAT LAST 9 FROM ARRAY
size=8;
array[size];
//IT SHOULD BE {1,2,4,5,6,7,8,9} now, but does it effect my program in any negative context?
int array[size] declares an array of size elements.
Outside of a declaration, array[size] access element size in array. It does not resize the array. If you do something like that without changing the value of size, it actually tries to access the element after the last element in the array; not a good idea. In this case, since you changed size to be one less than the original, it accesses the last element of the array, which is safe but does not do what you want.
You can not resize an array in C/C++ that is declared on the stack (one allocated on the heap with malloc could be reallocated to a different size, but you'd have trouble copying it as the newly allocated array of the new size is possibly at a completely different memory location; you'd have to save the old one, allocate a new one of the new size, copy the elements you want, and then free the old one.)
If you want something resizeable, you are in C++; use a container (vector, for example, but pick the one that most suits your needs).
And....I just saw arnav-borborah's comment; don't know how I missed that. You can't even declare the array like that, as size is not a compile time constant.
Until size variable is not constexpr, this
int size=9;
int array[size] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
is Variable length array, which is not part of c++ standard, only extension of some compilers.
Also automatic arrays are not resizeable, they have fixed size since declaration until they goes out of scope.
You should use some STL container, like std::array, std::vector.
std::array needs to know size at compile time, so there is the best approach, std::vector, which is easy to use and resizeable.
// #include<vector>
std::vector<int> array { 1,2,3,4,5,6,7,8,9 }; // Uniform initialization
// Remove last element
array.pop_back(); // 'array' has now only 8 elements (1..8)
EDIT
As mentioned in comments, if you want to remove n-th element in vector, you may do
array.erase(array.begin()+n);
and job is done.
Hugely. say if you have a payload of 1GB and you Array.Resize the destination array in chunks of 10k then most of your application CPU and wait states will be resizing that array.
If you pre-allocate the array to 1GB, populating that array will be orders of magnitude faster. This is because every time you use Array.Resize.
The computer needs to move that memory in its entirety to another location in memory just to add the extra length you resized it by.
But of cause if you are dealing with very small arrays. This effect is not noticeable.
Related
I just wanted to know why are some arrays written like this?
int arr[] = {3, 4, 6, 9, 11};
Why can't it just be written like this instead?
int arr[5] = {3, 4, 6, 9, 11}
What's the benefit?
Why can't it just be written like this instead?
The premise is wrong. It can be written both ways.
What's the benefit?
The size is redundant information. We've already implicitly given the size 5 by providing 5 initialisers. Providing redundant information is a potential source of bugs during development when that information accidentally goes out of sync.
For example, if the programmer decides later that the last 11 wasn't supposed to be there and should be removed leaving 4 elements in the array, the programmer making that change might not notice that the size has to also be changed, leading to a case where the last element is not removed as intended but replaced with value initialised element instead.
If the size of the array is supposed to be the same as the number of initialisers, then it is safer to not specify that size explicitly. To not specify the size explicitly is to follow the "Don't Repeat Yourself" principle.
On the other hand, if the size of the array is always supposed to be 5 regardless of the number of initialisers, then specifying the size explicitly achieves that. I suspect that this case is rarer in practice (except when there are no initialisers at all). Note that you should probably use a constant variable instead of a magic number for the size.
When you don't write any number into brackets, it means the array will have size equal to count of elements intialized with.
When you put there some number, you are giving the array a size.
int arr[] = {1, 7, 5}; // Size of the array is 3
int arr[3] = {1, 7, 5}; // Size of the array is 3
int arr[5] = {1, 7, 5}; // Size of the array is 5
Declaring with defined size is good when you know that you will need this count of items, but you don't have the items yet.
Without defined size it is simply easier to write.
I have the following array in my program:
int foo[] = {1,2,3,4,5};
//Do something with foo, but then there's no use with it afterwards
Since I need a lot more "single-use" arrays just like this, I want to re-define it like the following:
foo[] = {5,2,3}; //Raises an error
Note the array size could vary.
The only solution I've got is to create a new array for each re-definition, but that would be too much storage.
Is there any way of re-defining? Or is there any other solutions?
As the array must be able to vary its size, you could consider using std::vector instead of raw arrays and reassigning the vector whenever you need a new "array":
#include <vector>
#include <cassert>
int main() {
std::vector<int> foo = {1, 2, 3, 4, 5};
assert(foo.size() == 5);
foo = {5, 2, 3}; // <-- reassign
assert(foo.size() == 3);
}
The assignment replaces the vector's contents with those of the initializer list. No additional memory allocation will occur if the vector has enough capacity to store it.
Well, an array is not a first class object, but looks more like the beginning of a memory zone that will contain a sequence of objects. Because of that, the C++ does not allow to directly assign to an array. Full stop (BTW the ancestor C language does not either).
Workarounds:
use a pointer to a dynamic array. Simple but it will require you to initialize the content of each new array. And you are supposed to take care of freeing the array before reusing the pointer - not really the C++ philosophy...
use a vector. Exactly the previous way but nicely encapsulated in the vector class that will take care of allocation management and current size for you
use one single array of the size of the longuest arrays you want to uses and copy the expected data there
In those ways (except for the vector which is much more programmer friendly, you are supposed to keep track of the current used length
But if the reason is to save memory, the simplest and most efficient way is to directly use a pointer to initialized arrays. If you can extract the initialization data at run time, it must be present somewhere since build time, so why not directly use that memory(*)? The only downside I can imagine is that you will have track the length of the pointed array.
There is one notable exception. In some embedded system, initialization data can be stored in read only memory. In that case, you cannot directly use that memory if you need to write in it...
You can always just open & close a new scope for the lifetime of such "temporary" variables:
void bar() {
{
int foo[] = {1, 2, 3, 4, 5};
// Do something with the first foo
}
{
int foo[] = {5, 2, 3};
// Do something with the second foo
}
}
How do I remove an element of an array and shift the remaining elements down. So, if I have an array,
array[]={1,2,3,4,5}
and want to delete 3 and shift the rest so I have,
array[]={1,2,4,5}
How would I go about this in the least amount of code?
You just need to overwrite what you're deleting with the next value in the array, propagate that change, and then keep in mind where the new end is:
int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// delete 3 (index 2)
for (int i = 2; i < 8; ++i)
array[i] = array[i + 1]; // copy next element left
Now your array is {1, 2, 4, 5, 6, 7, 8, 9, 9}. You cannot delete the extra 9 since this is a statically-sized array, you just have to ignore it. This can be done with std::copy:
std::copy(array + 3, // copy everything starting here
array + 9, // and ending here, not including it,
array + 2) // to this destination
In C++11, use can use std::move (the algorithm overload, not the utility overload) instead.
More generally, use std::remove to remove elements matching a value:
// remove *all* 3's, return new ending (remaining elements unspecified)
auto arrayEnd = std::remove(std::begin(array), std::end(array), 3);
Even more generally, there is std::remove_if.
Note that the use of std::vector<int> may be more appropriate here, as its a "true" dynamically-allocated resizing array. (In the sense that asking for its size() reflects removed elements.)
You can use memmove(), but you have to keep track of the array size yourself:
size_t array_size = 5;
int array[5] = {1, 2, 3, 4, 5};
// delete element at index 2
memmove(array + 2, array + 3, (array_size - 2 - 1) * sizeof(int));
array_size--;
In C++, though, it would be better to use a std::vector:
std::vector<int> array;
// initialize array...
// delete element at index 2
array.erase(array.begin() + 2);
std::copy does the job as far as moving elements is concerned:
#include <algorithm>
std::copy(array+3, array+5, array+2);
Note that the precondition for copy is that the destination must not be in the source range. It's permissible for the ranges to overlap.
Also, because of the way arrays work in C++, this doesn't "shorten" the array. It just shifts elements around within it. There is no way to change the size of an array, but if you're using a separate integer to track its "size" meaning the size of the part you care about, then you can of course decrement that.
So, the array you'll end up with will be as if it were initialized with:
int array[] = {1,2,4,5,5};
You can't achieve what you want with arrays. Use vectors instead, and read about the std::remove algorithm. Something like:
std::remove(array, array+5, 3)
will work on your array, but it will not shorten it (why -- because it's impossible). With vectors, it'd be something like
v.erase(std::remove(v.begin(), v.end(), 3), v.end())
Depending on your requirements, you may want to use stl lists for these types of operations. You can iterate through your list until you find the element, and erase the element. If you can't use lists, then you'll have to shift everything yourself, either by some sort of stl algorithm or manually.
If you are most concerned about code size and/or performance (also for WCET analysis, if you need one), I think this is probably going to be one of the more transparent solutions (for finding and removing elements):
unsigned int l=0, removed=0;
for( unsigned int i=0; i<count; i++ ) {
if( array[i] != to_remove )
array[l++] = array[i];
else
removed++;
}
count -= removed;
Just so it be noted: If the requirement to preserve the elements order is relaxed it is much more efficient to replace the element being removed with the last element.
Programming Hub randomly provided a code snippet which in fact does reduce the length of an array
for (i = position_to_remove; i < length_of_array; ++i) {
inputarray[i] = inputarray[i + 1];
}
Not sure if it's behaviour that was added only later. It does the trick though.
It reduces length indeed. However, if we speak about int arrays, there is a difference between length and size.
Size tells us about a capacity of a given array, how much we can store in it.
Length of an array tells us about how many items are there actually.
This question is bit old.
Try using standard library provided containers. These are designed by experts and very well tested. Moreover future developments of standard library algorithms are designed to suite these standard library containers.
If for some reason you have to stick to array, then try using std::array
std::array<int, 5> array = { 1,2,3,4,5 };
//std::remove - The elements that are not deleted are moved to the front of the array,
//and returns the iterator of the element from where it can be completely erased.
auto itr = std::remove(array.begin(), array.end(), 3);
//New array with new size
std::array<int,4> newArray;
std::copy(array.begin(), itr, newArray.begin());
The same thing can be done without using std::array also. But as said earlier for many other benifits prefer to go with std::array
int array[] = { 1,2,3,4,5 };
auto itr = std::remove(std::begin(array), std::end(array), 3);
int newArray[4];
std::copy(std::begin(array), itr, std::begin(newArray));
How do I remove an element of an array and shift the remaining elements down. So, if I have an array,
array[]={1,2,3,4,5}
and want to delete 3 and shift the rest so I have,
array[]={1,2,4,5}
How would I go about this in the least amount of code?
You just need to overwrite what you're deleting with the next value in the array, propagate that change, and then keep in mind where the new end is:
int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// delete 3 (index 2)
for (int i = 2; i < 8; ++i)
array[i] = array[i + 1]; // copy next element left
Now your array is {1, 2, 4, 5, 6, 7, 8, 9, 9}. You cannot delete the extra 9 since this is a statically-sized array, you just have to ignore it. This can be done with std::copy:
std::copy(array + 3, // copy everything starting here
array + 9, // and ending here, not including it,
array + 2) // to this destination
In C++11, use can use std::move (the algorithm overload, not the utility overload) instead.
More generally, use std::remove to remove elements matching a value:
// remove *all* 3's, return new ending (remaining elements unspecified)
auto arrayEnd = std::remove(std::begin(array), std::end(array), 3);
Even more generally, there is std::remove_if.
Note that the use of std::vector<int> may be more appropriate here, as its a "true" dynamically-allocated resizing array. (In the sense that asking for its size() reflects removed elements.)
You can use memmove(), but you have to keep track of the array size yourself:
size_t array_size = 5;
int array[5] = {1, 2, 3, 4, 5};
// delete element at index 2
memmove(array + 2, array + 3, (array_size - 2 - 1) * sizeof(int));
array_size--;
In C++, though, it would be better to use a std::vector:
std::vector<int> array;
// initialize array...
// delete element at index 2
array.erase(array.begin() + 2);
std::copy does the job as far as moving elements is concerned:
#include <algorithm>
std::copy(array+3, array+5, array+2);
Note that the precondition for copy is that the destination must not be in the source range. It's permissible for the ranges to overlap.
Also, because of the way arrays work in C++, this doesn't "shorten" the array. It just shifts elements around within it. There is no way to change the size of an array, but if you're using a separate integer to track its "size" meaning the size of the part you care about, then you can of course decrement that.
So, the array you'll end up with will be as if it were initialized with:
int array[] = {1,2,4,5,5};
You can't achieve what you want with arrays. Use vectors instead, and read about the std::remove algorithm. Something like:
std::remove(array, array+5, 3)
will work on your array, but it will not shorten it (why -- because it's impossible). With vectors, it'd be something like
v.erase(std::remove(v.begin(), v.end(), 3), v.end())
Depending on your requirements, you may want to use stl lists for these types of operations. You can iterate through your list until you find the element, and erase the element. If you can't use lists, then you'll have to shift everything yourself, either by some sort of stl algorithm or manually.
If you are most concerned about code size and/or performance (also for WCET analysis, if you need one), I think this is probably going to be one of the more transparent solutions (for finding and removing elements):
unsigned int l=0, removed=0;
for( unsigned int i=0; i<count; i++ ) {
if( array[i] != to_remove )
array[l++] = array[i];
else
removed++;
}
count -= removed;
Just so it be noted: If the requirement to preserve the elements order is relaxed it is much more efficient to replace the element being removed with the last element.
Programming Hub randomly provided a code snippet which in fact does reduce the length of an array
for (i = position_to_remove; i < length_of_array; ++i) {
inputarray[i] = inputarray[i + 1];
}
Not sure if it's behaviour that was added only later. It does the trick though.
It reduces length indeed. However, if we speak about int arrays, there is a difference between length and size.
Size tells us about a capacity of a given array, how much we can store in it.
Length of an array tells us about how many items are there actually.
This question is bit old.
Try using standard library provided containers. These are designed by experts and very well tested. Moreover future developments of standard library algorithms are designed to suite these standard library containers.
If for some reason you have to stick to array, then try using std::array
std::array<int, 5> array = { 1,2,3,4,5 };
//std::remove - The elements that are not deleted are moved to the front of the array,
//and returns the iterator of the element from where it can be completely erased.
auto itr = std::remove(array.begin(), array.end(), 3);
//New array with new size
std::array<int,4> newArray;
std::copy(array.begin(), itr, newArray.begin());
The same thing can be done without using std::array also. But as said earlier for many other benifits prefer to go with std::array
int array[] = { 1,2,3,4,5 };
auto itr = std::remove(std::begin(array), std::end(array), 3);
int newArray[4];
std::copy(std::begin(array), itr, std::begin(newArray));
I want to allocate an array of vectors in a function. Every vector should be initiated with a size of 0. Afterwards I want to push pointers to objects T to my vectors. Finally I want have a grid with a list of references in every cell. I am stuck at the initialization of the vectors. It seems that they are not allocated ?
typedef std::vector<T*> GridCell;
GridCell* mGrid;
...
int gridSize = 5;
mGrid = new GridCell[gridSize];
mGrid[gridSize] = { GridCell() }; //runtime error here
This might be possibly duplicated to other posts, but I couldn't find one that solves this issue 100%.
mGrid = new GridCell[gridSize];
This line not only allocates an array, but it default constructs all of the entries too!
mGrid[gridSize]
This is an out of bounds error; as the array has length 5, the only valid indices are 0, 1, 2, 3, 4. Trying to access an element at index 5 is undefined behavior.
vector<GridCell> mGrid(5);
// vector<GridCell> mGrid(5, GridCell()); // Same thing as the line above
This is what you should have done instead. With modern C++, it's pretty rare that you should ever have to use new; there are standard objects that serve most of the purposes people once used new for (e.g. using vector instead of dynamically an array), there are smart pointers for most of the remaining cases, and for the few cases still remaining, you're usually better served by writing your own custom class whose purpose in life is to be a wrapper around whatever you're doing with new.