Dynamically allocated array transmitting to the function by reference - c++

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)

Related

Helper function to construct 2D arrays

Am I breaking C++ coding conventions writing a helper function which allocates a 2D array outside main()? Because my application calls for many N-dimensional arrays I want to ensure the same process is followed. A prototype which demonstrates what I am doing :
#include <iostream>
// my helper function which allocates the memory for a 2D int array, then returns its pointer.
// the final version will be templated so I can return arrays of any primitive type.
int** make2DArray(int dim1, int dim2)
{
int** out = new int* [dim1];
for (int i = 0; i < dim2; i++) { out[i] = new int[dim2];}
return out;
}
//helper function to deallocate the 2D array.
void destroy2DArray(int** name, int dim1, int dim2)
{
for (int i = 0; i < dim2; i++) { delete[] name[i]; }
delete[] name;
return;
}
int main()
{
int** test = make2DArray(2,2); //makes a 2x2 array and stores its pointer in test.
//set the values to show setting works
test[0][0] = 5;
test[0][1] = 2;
test[1][0] = 1;
test[1][1] = -5;
// print the array values to show accessing works
printf("array test is test[0][0] = %d, test[0][1] = %d, test[1][0] = %d, test[1][1] = %d",
test[0][0],test[0][1],test[1][0],test[1][1]);
//deallocate the memory held by test
destroy2DArray(test,2,2);
return 0;
}
My concern is this may not be memory-safe, since it appears I am allocating memory outside of the function in which it is used (potential out-of-scope error). I can read and write to the array when I am making a single small array, but am worried when I scale this up and there are many operations going on the code might access and alter these values.
I may be able to sidestep these issues by making an array class which includes these functions as members, but I am curious about this as an edge case of C++ style and scoping.
There is a difference between allocating 2D arrays like this and what you get when you declare a local variable like int ary[10][10] that based on your statement
My concern is that this operation may not be memory-safe, since it
appears that I am allocating memory for an array outside of the
function in which it is used (potential out-of-scope error)
I am guessing you do not fully understand.
You are allocating arrays on the heap. Declaring a local variable like int ary[10][10] places it on the stack. It is the latter case where you need to worry about not referencing that memory outside of its scope-based lifetime; that is, it is the following that is totally wrong:
//DON'T DO THIS.
template<size_t M, size_t N>
int* make2DArray( ) {
int ary[M][N];
return reinterpret_cast<int*>(ary);
}
int main()
{
auto foo = make2DArray<10, 10>();
}
because ary is local to the function and when the stack frame created by the call to make2DArray<10,10> goes away the pointer the function returns will be dangling.
Heap allocation is a different story. It outlives the scope in which it was created. It lasts until it is deleted.
But anyway, as others have said in comments, your code looks like C not C++. Prefer an std::vector<std::vector<int>> rather than rolling your own.
If you must use an array and are allergic to std::vector, create the 2d array (matrix) as one contiguous area in memory:
int * matrix = new int [dim1 * dim2];
If you want to set the values to zero:
std::fill(matrix, (matrix + (dim1 * dim2)), 0);
If you want to access a value at <row, column>:
int value = matrix[(row * column) + column];
Since the matrix was one allocation, you only need one delete:
delete [] matrix;

C++ returning array

I am trying to wrap my mind around arrays and pointers in C++.
I am trying to write a function that allocates memory for an int array of variable size. The array is then filled with random numbers and returned.
The problem I have is assigning values with pointers.
This is the function:
int* getArray(int length) {
int* values = new int[length];
for (int i=0; i<length; i++) {
values[i]=i;
}
return values;
}
And it works just fine.
But, if I change it to this:
int* getArray(int length) {
int* values = new int[length];
for (int i=0; i<length; i++, values ++) {
*values=i;
}
return values;
}
It doesn't work.
Can someone explain to me why I cannot do this?
This is the main method that I used to print all the values:
int main() {
int* v = getArray(100);
for(int i=0;i<100;i++, v++) {
cout << *v <<endl;
}
delete[] v;
return 0;
}
I think it is because the new operator allocates new memory in the heap and not in the stack so the pointer might actually point to the wrong direction.
But, if that is true, why is the main method working?
Side note: I do not get any kind of warning or error, but the output is just a bunch of zeros and some random numbers.
I am using the GCC compiler on Ubuntu.
values++ is modifying values, which eventually forms the function return value.
i.e. you return one past the end of the allocated array. That in itself is perfectly legal C++.
But things go very badly wrong at the function call site: you access invalid elements of the array (which very informally speaking are your "random numbers"), and calling delete[] on that is also undefined behaviour. Boom!

Why shouldn't I receive 2D arrays by **&?

Reading some others questions about passing 2d arrays I realized that no one answered this:
void func(int **&matrix) {
matrix[2][1]=5;
...
}
int main() {
int **matrix;
matrix=new int*[10];
for(int q=0;q<10;q++)
matrix[q] = new int[5];
func(matrix);
...
}
I tested it and it works. Any problem with this code?
The answer is the same as why shouldn't you use int*& when passing 1D arrays represented via a pointer. You want to use the reference whenever you want to modify the pointer passed to your function. In your case, you are just accessing the elements that are pointed by, no need to modify the pointer itself. So, there is no real need for a reference, although it is not technically incorrect to use a reference.
Example of when it may make sense to use a reference:
f(int*& p)
{
// do something with the memory pointed by p
for(int i = 0; i < 10; ++i)
std::cout << ++p[i]; // ok, modify the memory location p+i points to
delete[] p; // deallocation
p = nullptr; // nullify p, if you want to modify what you passed, you need the reference
}

Calling array with variable size as parameter

I was trying to make a program in which the user decides the dimensions of a 2-D array.
I'm getting an error on the function definition while compiling. Why is this wrong and what would be the correct way to do it?
I'm using the Dev-C++ 5.7.1 compiler (if that's relevant).
#include<iostream>
using namespace std;
int R=0,C=0;
void func(int);
int main() {
cin>>R>>C;
int array[C][R];
// DO STUFF HERE
func(array);
// DO SOME MORE STUFF
return 0;
}
void func(int arr[][R]) {
// DO STUFF HERE
}
ISO-C++ forbids VLAs. To dynamically allocate an array you'll either need to do some raw pointer tricks or use a vector of vectors.
vector of vectors approach:
std::cin >> R >> C;
std::vector<std::vector<int>> array(R, std::vector<int>(C));
The signature for func then becomes (const correctness may be different)
void func(const std::vector<std::vector<int>>& v);
The above is the easier, more maintainable, safer, shorter solution.
With pointers and pointers to pointers you can do it but it becomes more complicated, and you need to delete everything that you new
int R, C;
std::cin >> R >> C;
int **array = new int*[R]; // allocates space for R row pointers
for (int i = 0; i < R; ++i) {
array[i] = new int[C]; // for each row, allocate C columns
}
func(R, C, array);
//then delete everything
for (int i = 0; i < R; ++i) {
delete [] array[i]; // delete all of the ints themselves
}
delete [] array; // delete the row pointers.
with the signature for func being
void func(int r, int c, int **arr);
again, vector of vectors will be a lot easier on you.
An array can be located in two different memory regions - on the stack, or on the heap.
Array like you specified, is located on the stack.
int array[SIZE];
when an array is located on the stack, the compiler needs to know in advance what is its size, therefor SIZE must be a constant expression (known at compile time), and sometimes a defined value (set using #define SIZE 10).
if you want to create an array of unknown size (will be determined in runtime), you need to create the array on the heap, like this:
int **array = new int*[C];
for(int i = 0;i<C; i++)
array[i] = new int[R];
later on, you must remember to delete everything you dynamically allocated (everything you used new on)
for(int i = 0;i<C; i++)
delete[] array[i];
delete[] array;
note the use of delete[], because we are deleting an array (array is an array of arrays of ints, array[i] is an array of ints)
I would recommend passing in a pointer to the array, and two variables for R and C. Then it's up to you to make sure you use pointer math correctly to stay within the bounds of the array.
Otherwise set this up as a template, but you'll still probably need to know the sizes of R & C.

C++ Initializing a Global Array

Hey everyone. I am an experienced java programmer and am just learning C++.
Now I have a bit of a beginner's problem. I have an array variable x of type int.
The user will input the size of x in method B. I want to use x in method A.
void method A()
{
using int x [] blah blah blah
}
void method B()
{
int n;
cin >>n;
int x [n]; // How can I use this int x in method A without getting error: storage size x is unknown.
// Or the error 'x' was not declared in this scope.
}
EDIT: Parameter passing isn't a solution I am looking for.
DOUBLE EDIT: I do know about the vector option, but my program is cramming on time. I am creating an algorithm where every millisecond counts.
BTW I found out a way of doing it.
int x [] = {}
method B();
method A () { blah blah use x}
method B () {/*int*/ x [n]}
If you actually want an array and not a vector, and you want that array dynamically sized at runtime, you would need to create it on the heap (storing it in a pointer), and free it when you're done.
Coming from Java you need to understand that there's no garbage collection in C++ - anything you new (create on the heap) in an object you will want to clean up in the destructor with delete.
class foo
{
private:
int *array;
public:
foo() { array = NULL; };
~foo()
{
if (array != NULL)
delete [] array;
}
void createArray()
{
array = new int[5];
}
};
More info at: http://www.cplusplus.com/doc/tutorial/dynamic/
This is a version of your example that works in c++.
#include <iostream>
int *my_array;
void methodA(a,b){
my_array[a] = b;
}
int methodB(){
int n;
std::cin >> n;
my_array = new int[n];
}
int main(){
int x;
x = methodB();
methodA(x-1, 20);
delete [] my_array;
return 0;
}
Use a vector:
std::vector<int> x(n);
then pass that to method A as an argument of type std::vector<int> const &.
Edit: Or make the vector a data member of your class and set it with:
size_t n;
std::cin >> n;
x.resize(n);
In C++ you can't directly size an array with a runtime value, only with constants.
You almost certainly want vector instead:
std::vector<int> x(n);
EDIT: flesh out answer.
I can't quite tell if you are trying to learn about arrays, or if you are trying to solve some practical problem. I'll assume the latter.
The only way for method A to have access to any variable is if it is in scope. Specifically, x must either be:
a local, including a parameter (but you said no to parameter passing)
a class member, or
a global
Here is a solution in which x is a class member:
class C {
public:
std::vector<int> x;
void A() {
std::cout << x[2] << "\n"; // using x[], for example.
}
void B() {
int n;
cin >> n;
x = std::vector<int>(n); // or, as others have pointed out, x.resize(n)
}
};
Be aware that arrays in C++ are much more basic (and dangerous) than in Java.
In Java, every access to an array is checked, to make sure the element number you use is within the array.
In C++, an array is just a pointer to an allocated area of memory, and you can use any array index you like (whether within the bounds of the array, or not). If your array index is outside the bounds of the array, you will be accessing (and modifying, if you are assigning to the array element!) whatever happens to be in memory at that point. This may cause an exception (if the memory address is outside the area accessible to your process), or can cause almost anything to happen (alter another variable in your program, alter something in the operating system, format your hard disk, whatever - it is called "undefined behaviour").
When you declare a local, static or global array in C++, the compiler needs to know at that point the size of the array, so it can allocate the memory (and free it for you when it goes out of scope). So the array size must be a constant.
However, an array is just a pointer. So, if you want an array whose size you don't know at compile time, you can make one on the heap, using "new". However, you then take on the responsibility of freeing that memory (with "delete") once you have finished with it.
I would agree with the posters above to use a vector if you can, as that gives you the kind of protection from accessing stuff outside the bounds of the array that you are used to.
But if you want the fastest possible code, use an allocated array:
class C {
int [] x;
void method A(int size)
{
x = new int[size]; // Allocate the array
for(int i = 0; i < size; i++)
x[i] = i; // Initialise the elements (otherwise they contain random data)
B();
delete [] x; // Don't forget to delete it when you have finished
// Note strange syntax - deleting an array needs the []
}
void method B()
{
int n;
cin >> n;
cout << x[n];
// Be warned, if the user inputs a number < 0 or >= size,
// you will get undefined behaviour!
}
}