Why are some ARRAYS written like this in C++? - c++

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.

Related

Sorting int's in C++, when variables are allocated next to each others in memory?

So i came up with simple idea of sorting separate int variables, which are declared next to each other. For example:
int a=2, b=6, c=3, d=5;
sort(&a, &d+1);
cout<<a<<" "<<b<<" "<<c<<" "<<d<<endl;
Before saying me that I should not use above technique, because of multiple reasons, I would like to say that it is useful in competitive programming when you have to type short and possibly clean code. Unfortunately I fell somehow of bad when using above code, and I would like to know when C++ allocate variables in neighbour cells, and what is probability or guaranty that it is going to happen.
I would like to know when C++ allocate variables in neighbour cells
The standard never explicitly guarantees this.
It also doesn't matter much since if you iterate past the bounds of the object (beyond one past the object) then the behaviour of the program is undefined.
Where the standard does guarantee that objects are adjacent is arrays. Furthermore, you can use pointers to iterate over the elements of arrays. Hence, your example can be correctly written like this:
int arr[] {2, 6, 3, 5};
std::sort(std::begin(arr), std::end(arr));
for (int a : arr) {
std::cout << a << ' ';
}
std::cout << '\n';
There is no guarantee that your 4 variables will be next to each others in memory. It will depends of so many things that you can't predict it.
But with an array, it is always the case :
int ints[] = {2, 6, 3, 5};
sort(ints, ints + 4);

Is there any way to re-define an array in c++?

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
}
}

Resizing array, does this code influence it badly in any way?

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.

Creating an unmodifiable 2d array in c++

Quick background, I have some experience with java and currently new to c++.
My question comes from an assignment in which we had to create 4 different magic squares, but for the nature of this particular question they can be any 2d array, so long as they are "exact" in values, only that they appear differently from each one. What I mean by that is if one 2d array looked like:
1 2 3
4 5 6
7 8 9
the next one would be rotated 90 degrees
7 4 1
8 5 2
9 6 3
and so on..
To make the first matrix I simply made a 2d array and created it using the magic square algorithm (irrelevant)
int** square = new int*[size]();
for (int i = 0; i<size; i++) {
square[i] = new int[size]();
}
//set values to square .. irrelevant to show, could be anything
//way down the code
int** secondSquare = square;
For the second third and fourth ones all I would need to do is rotate the previous one to get the next rotated square. My problem however wasn't that I could not flip the arrays, but that while trying to flip them the values for the first square were also changing.
Obviously this is more of a problem about being able to access the data in square and not change it while trying to add them to secondSquare.
I tried making it so square was a modifiable pointer w constant unmodifiable values.
const int** square = new int*[size];
The problem with this is that I have to assign values after to square so this cannot be done. Also when I initialize secondSquare it gives me an error since it is of type int** and not const int**.
Any better ways to handle problems with accessing data without changing values and setting both arrays (or objects really) properly on initialization?
You would do well to avoid using raw pointers and new entirely . That should really come in the advanced section of any C++ course.
Here is one way:
array< array<int,3>, 3> square = {{ {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }};
square[1][1] = 12; // optional
const auto &c_square = square;
Now c_square is a const accessor of square that you can use later and avoid risk of modifying square.
The problem is int** secondSquare = square; copies the address of the square pointer to secondSquare. So in the end you have two (three, four) pointers pointing to exact same place in memory. Think about it like you have one square created but you try to access it through four different pointers.
What you want to do is to allocate memory for 4 different int** pointers.
To create a 2d array, you would declare it as const:
const int array_2d[3][3] =
{
0, 1, 2,
3, 4, 5,
6, 7, 8
};
In my experience, the better method is to declare it as static const so you are telling the compiler that there is only 1 read only instance:
static const int array_2d[3][3] =
{
0, 1, 2,
3, 4, 5,
6, 7, 8
};
The static allows for the compiler to place the data in a read-only section of the executable and access it directly, rather than copying it from Read-Only to the stack before usage (I've seen compilers emit this kind of code).

Copy arrays-vectors

This might be too basic, but I would like to ask. I have my code in Java that copies the start array to newStart and assigns the last element to another array.
int[] newStart= Arrays.copyOf(start, start.length + 1);
newStart[start.length] = array[i];
I converted it to my C++ version with vectors as:
vector<int> newStart(5); //Doesnt have to be 5, sth not known
newStart.insert(newStart.end(), start.begin(), start.end());
newStart[start.size()] = array[i];
However, my code doesn't do what I require. That adds the vector one to the other's end, and makes new assignments accordingly. What is the right way to do that?
C++ vectors don't auto-resize on element access (through operator[] nor at method). Replace the last line with either
newStart.push_back(array[i]);
or
newStart.resize(start.size() + 1);
newStart[start.size()] = array[i];
(the former being more efficient, because it does not default-initialize the element first)
I believe Java arrays don't auto-resize either, so I wouldn't expect the Java code to work either (but it will give exception while the C++ code will make daemons fly out of your nose or whatever else nasty the compiler will think of).
Edit: Reading the question again, the code there is actually defined, but the more wrong.
vector<int> newStart(5); //Doesnt have to be 5, sth not known
This statement actually creates a vector that contains 5 (or whatever) default initialized elements, which in case of int is 0. So now you have
{0, 0, 0, 0, 0}
For sake of example let's say start contains {1, 2, 3, 4, 5, 6, 7}.
newStart.insert(newStart.end(), start.begin(), start.end());
vector::insert adds new elements extending the array and moving the following elements as necessary. The insert is before end, so it will append to the vector, resulting in:
{0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7}
I don't think this is what you wanted. It looks like you wanted a copy of start. Which you'd simply create by copy constructing: vector<int> newStart(start).
newStart[start.size()] = array[i];
Now newStart has the initial 5 zeroes and the elements from start, so it's size is start.size() + 5 and therefore it does have index start.size(). It is the 5th element from end. So per above example, this will modify the vector to:
{0, 0, 0, 0, 0, 1, 2, 1, 4, 5, 6, 7}
^
To append start[0] to the end, use push_back as per above.
Also remember, that Java arrays are reference types, where assignment just shares reference to the same array, but C++ vectors are value types where the content is copied on assignment.
I'm a little confused by the mixing of Java and C++. Hopefully one of the explinations below will help.
If you're in C++, vector has an overloaded operator= so you can just type
newvector = oldvector;
and it will copy.
If you're in java, you can use the copy constructor ex:
Vector v2 = new Vector(v1);
Try this:
for (std::vector<int>::iterator it = start.begin() ; it != start.end(); ++it) {
newStart.push_back (*it);
}
Use std::copy algorithm and back_inserter iterator.
Sample code:
#include <iterator>
#include <vector>
#include <algorithm>
int main () {
std::vector<int> src;
std::vector<int> dest;
std::copy(src.begin(),src.end(),back_inserter(dest));
}