How to create an array of pointers without using vector - c++

I saw that an array of pointers can be created using vector, however, I don't want that. Is the example below a way to create a pointer to int array?
#include <iostream>
using namespace std;
int main() {
int* arr[4];
for (int i=0; i<4; ++i) {
cout<<endl<<arr[i];
}
}
This makes a pointer to int array and it displays the memory address of each index in the array. Now I have few questions. Is it a proper way to create a pointer to int array without a vector? Also, if I want to initialize a value inside each memory address in the given example, how is it done? And lastly why is &arr equal to arr?

While &arr and just plain arr may both give you the same address, they are both very different.
With &arr you get a pointer to the array, and the type of it is (in your case) int* (*)[4].
When you use arr it decays to a pointer to the first element and the type is (again, in your case) int**.
Same address, but different types.
As for the array itself, it's defined fine, you have an array of four pointers to int. However, you do not initialize the contents of the array, which means that the contents is indeterminate, and using those pointers in any way (even just printing them) leads to undefined behavior.

Your proposed way doesn't make pointer to int array. Instead of that it makes a pointer to pointer to an int array. Usually the name of any array represent a pointer to it self. Or &arr[0] also represent it.
So I hope that you got the answer for why &arr equal arr.
Creating a pointer to int array
int arr[4];
int* p = arr; //pointer to int array
Initializing each element in array
(1) Using pointer arithmetic
int size = 4;
int* p = arr;
for (int i = 0; i < size; i++)
{
*p = i; // assigning each element i
p++; //pointing to next element
}
(2) Using operator []
int size = 4;
for (int i = 0; i < size; i++)
{
arr[i] = i; // assigning each element i
}

&arr gives you the address of array which starts with base address ie address of first element.
arr gives the address of first element.
hence u get same result for both

Related

Dynamically allocated array transmitting to the function by reference

I am having difficulties passing dynamically allocated array to the function by reference.
"The array should be transmitted to the function by reference".
My program should take n amount of integers and find out the minimum. That minimum should be added to all the arrays that the user has entered. But the BY REFERENCE part kills me. I tried (int &x[],int &n) but failed.
PLease help, thank you very much.
void add_min(int x[], int n)
{
int add[n];
int mini = x[0];
int i;
for(i = 0; i < n; i++)
{
if(x[i] < mini)
{
mini = x[i];
}
}
for(i = 0; i < n; i++)
{
add[i] = x[i] + mini;
}
for(i = 0; i< n ; i++)
{
cout<<add[i]<<endl;
}
}
int main()
{
int *x;
int n;
cout<<"Enter the amount of integers"<<endl;
cin>>n;
x = new int[n];
cout<<"Enter the integers"<<endl;
for(unsigned i = 0; i < n; i++)
{
cin>>x[i];
}
add_min(x,n);
delete x;
return 0;
}
Dynamically allocated arrays cannot be in a named variable and you cannot have a reference to one.
When you call new[] the array is allocated somewhere in the memory, and the call returns the address of the first object in that array. You store the address in a pointer variable. The pointer is not an array, it simply points to the first element.
You can pass a pointer by reference to a function like this:
void foo(int*& ptr)
If your assignment asks you to pass an array by reference, then you may not allocate the array dynamically. In that case, this is how you declare the argument to be a reference to an array:
void foo(int (&arr)[10])
Note that the size must be known at compile time. You can use a template argument to generate functions for different sizes of arrays.
If the assignment does ask you to allocate the array dynamically, then they probably intend you to pass a pointer by reference.
The problem I see here is the following to pass in via reference a:
dynamically allocated array
The only way you can have dynamic allocation to happen is via returning a pointer. The syntax for passing in an array to a function, as you have correctly guessed is:
void add_min(int x[], int n) { ... }
Certainly you can treat the array as a pointer, and then you get:
void add_min(int* x, int n) { ... }
now comes the problem with the reference
The syntax for passing in an array via reference to the application is:
void add_min(int (&x)[3]) { ... }
but in this case you need to actually know the size of it, so the array is not dynamically allocated.
To circumvent the need to know the size of the array, we can do some template magic, like:
template<int n>
void add_min(int (&x)[n]) { ... }
but again, this will need to be called with a statically allocated array (int x[124]), not a dynamic one.
But arrays are always passed in via reference, they are never copied to the stack, so your version of the code is correct.
First of all, you're using C++ so you shouldn't use pointers but std::vector. It'll be easier and you won't create memory leaks.
Second, you're passing pointer, not array. There are not the same: https://stackoverflow.com/a/1641963/1351828
So you're pssing the pointer to the first element. If you want to change elements in 'array' you can just pass pointer by value. If you want to allocate new 'array' and change it in a function, pass the pointer by reference:
void add_min(int &x[], int n)

What value does a pointer to pointer get assigned when points to a dynamically allocated memory?

Consider the following case:
int **my_array = new int*[10];
What do we assign to my_array here?
my_array is a pointer that points to what?
Is there any way to iterate through my_array (the pointer) and set up a two-dimensional array of integers (and not int*)?
We assign to my_array the address of an array. The array contains pointers which can point to other arrays, but don't yet.
Yes, we can do this:
int **my_array = new int*[10];
for(int i=0; i<10; ++i)
my_array[i] = new int[13];
my_array[2][11] = 500;
What do we assign to my_array here?
You can assign an int* to the elements of my_array. E.g.
my_array[0] = new int[20];
or
int i;
my_array[0] = &i;
my_array is a pointer that points to what?
It points to an an array of 10 int* objects.
Is there any way to iterate through my_array (the pointer) and set up a two-dimensional array of integers (and not int*)?
Not sure what you are expecting to see here. An element of my_array can only be an int*.
If you want my_array to be a pointer to a 2D array, you may use:
int (*my_array)[20] = new int[10][20];
Now you can use my_array[0][0] through my_array[9][19].
PS If this is your attempt to understand pointers and arrays, it's all good. If you are trying to deploy this code in a working program, don't use raw arrays any more. Use std::vector or std::array.
For a 1D array, use:
// A 1D array with 10 elements.
std::vector<int> arr1(10);
For a 2D array, use:
// A 2D array with 10x20 elements.
std::vector<std::vector<int>> arr2(10, std::vector<int>(20));

The correct way to initialize a dynamic pointer to a multidimensional array? [duplicate]

This question already has an answer here:
How to properly work with dynamically-allocated multi-dimensional arrays in C++ [duplicate]
(1 answer)
Closed 7 years ago.
I've been having bad luck with with dynamic pointers when I range them to 2 dimensions and higher. For example I want a pointer to a 2D array. I know that:
int A[3][4];
int (*P)[4] = A;
Is completely legit (even if I don't completely understand why). Taking into consideration that:
int *P = new int[4];
works, I imagined that:
int **P = new int[5][7];
Would also work, but it's not. This code states the error:
Error: A value of type "(*)[7]" cannot be used to initialize an entity of
type "int **"
By seeing this the new part becomes a pointer to an array of 7 integers I made:
int (*P)[4] = new int[7][4];
And this does work but it's not what I want to accomplish. By doing it like that I'm limited to at least using a constant value for any subsequent dimension, but I want it to be fully defined at run time and therefore "dynamic".
How could I go and make this multidimensional pointer work??
Let's start with some basic examples.
When you say int *P = new int[4];
new int[4]; calls operator new function()
allocates a memory for 4 integers.
returns a reference to this memory.
to bind this reference, you need to have same type of pointer as that of return reference so you do
int *P = new int[4]; // As you created an array of integer
// you should assign it to a pointer-to-integer
For a multi-idimensional array, you need to allocate an array of pointers, then fill that array with pointers to arrays, like this:
int **p;
p = new int*[5]; // dynamic `array (size 5) of pointers to int`
for (int i = 0; i < 5; ++i) {
p[i] = new int[10];
// each i-th pointer is now pointing to dynamic array (size 10)
// of actual int values
}
Here is what it looks like:
To free the memory
For one dimensional array,
// need to use the delete[] operator because we used the new[] operator
delete[] p; //free memory pointed by p;`
For 2d Array,
// need to use the delete[] operator because we used the new[] operator
for(int i = 0; i < 5; ++i){
delete[] p[i];//deletes an inner array of integer;
}
delete[] p; //delete pointer holding array of pointers;
Avoid memory leakage and dangling pointers!
You want something like:
int **P = new int*[7];
p[0] = new int[5];
p[1] = new int[5];
...
Another approach would be to use a 1D array as an 2D array. This way you only have to allocate the memory once (one continous block);
int *array;
size_t row=5,col=5;
array = (int*)malloc(row*col*sizeof(int)) //or new int[row*col]
This would result in the same as "int array[5][5]".
to access the fields you just do:
array[1 //the row you want
* col //the number of columns
+2//the column you want
] = 4;
This is equal to:
array[1][2];
This performs bounds checking on some debug compilers, uses dynamic size and deletes itself automatically. The only gotcha is x and y are the opposite way round.
std::vector<std::vector<int>> array2d(y_size, std::vector<int>(x_size));
for (int y = 0; y < y_size; y++)
{
for (int x = 0; x < x_size; y++)
{
array2d[y][x] = 0;
}
}

How to access the array from the pointer?

I am trying to understand how pointers work but I do not know how a pointer to only the first element can be used to access all the array
int myArray[10];
for(int i=0; i<10; i++)
{
myArray[i] = 11*i;
}
int *p;
p = myArray;
//Now how do I access the complete array using the variable p
cout<<*p; //This only prints the first value, how to print all the values
You have to use while or for.
int i = 0;
while (i < 10)
{
cout << p[i];
i += 1;
}
Pointers and arrays are working in the same way. An array is nothing else than a pointer to the first element you allocated.
If you for example want to access pos 5, you can just write:
...
int *p;
p = myArray;
cout << p[5];
Since the compiler know that p is a pointer to an int, it will add the size of an int for each step (4 bytes in this case).
As long as you don't use pointers to void, the compiler does this for you.
You still have to keep track of the length of the array so you do not exceeds it since a pointer don't do that.
except for thr declaration, arrays and pointers con be used using the same syntax
(They are different in memory, meaning they still need to be treated differently)
Use like this,
int *p;
p = myArray;
for(int i=0;i<10;i++)
{
cout<<*(p+i);
}
The first element points to the first memory location of the elements in the array. So this:
myArray[0];
and
myArray;
point to the same location. You can use indexes on the pointer, just like you did to fill the array. So this:
int *p = myArray;
cout << p[0];
cout << p[1];
would access your other elements. You can use a for loop to access all the elements in the array, just like you did to populate it in the first place.
You can think of the name of an array as a pointer to its first element.
So, the line p = myArray; is simply copying the address of the first element of the array myArray into p.
Now the line cout<<*p; is obviously displaying the value of what's pointed by p, which is the first element of your array.
To display all the elements, you can simply use a for loop like you did before.

How do I pass a reference to an array, whose size is only known at run-time, as a function parameter?

I have an array that is being dynamically created based on user input, and I need to pass that array to a function where it will be manipulated and the results passed back out to the original array. When I try to use
void MyFunction(int (&MyArray)[])
my compiler complains that it doesn't know how big the array is.
You can't. You could use a std::vector though.
You can give a pointer to the first element of the array + a second parameter holding the size of the array.
If it's just an array, why not pass the array itself and its size as a second parameter? (by passing the array as an int* or int[], same thing as far as C++ is concerned).
As the value of the variable containing your array is only the pointer to the first element of your array, you don't end up killing your runtime by copying the contents of the array, but just a pointer which is as small as you can get in this case.
void MyFunction( int MyArray[], int size ) { /* edit the array */ }
int main() {
// read nrElements
// ...
// create the array
int *a = new int[nrElements];
// populate it with data
// ...
// and then
MyFunction(a, nrElements);
}
You should use a std::vector only if you want to resize the array in your function (e.g. add new elements to it), but otherwise you can just stick to this approach because it's faster.
Btw, the only case you would need a reference to an array is if you want to change the value of the variable you pass in when you call the function, as in, make it point to a different array. Like in:
void createMyArray(int* &array, int nrElements) {
array = new int[nrElements];
for (int i = 0; i < nrElements; ++i) {
array[i] = 0;
}
}
int *a = (int []) {1, 2, 3};
std::cout << a[0] << std::endl; // prints 1
createMyArray(a, 10);
// now a points to the first element of a 10-element array
std::cout << a[0] << std::endl; // prints 0
But you said the array is already created before providing it to the function, there's no point in using references.