Calling array with variable size as parameter - c++

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.

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;

Why do I have to free 2D array twice to avoid memory leak?

I am running into a memory leak problem when allocating a 2D array.
But I could not understand why the memory leaks.
My reasoning is that at Note A, I have already freed allocated memory, since data_[0] == data_, why do I have to do the free at Note B?
class Matrix {
public:
Matrix(int r, int c) {
this->rows = r;
this->cols = c;
data_ = new int*[r];
for (int i = 0; i < r; i++) {
data_[i] = new int[c];
}
}
~Matrix() {
for (int i = 0; i < this->rows; i++) {
delete [] data_[i]; // Note A;
}
delete[] data_; // Note B; <-- not doing this line will leak memory, but why?
}
private:
int rows;
int cols;
int **data_;
};
What you post there isn't really a 2D array, it's a 1D array-of-pointers (data_), and then you allocate a separate array-of-ints for each element of the first array (so data_[0] is an array of c ints, data_[1] is an array of c ints, and so on).
Given that, it's natural that you'll have to do one delete[] in your destructor for each new that you performed earlier in your constructor.
A graphical diagram of your memory allocations and how they point to each other might look like this (if c==6 and you have set all of your arrays' integers to 0):
A real 2D array allocation would look like this: int * array2D = new int[6][8];, but of course C++ only supports 2D arrays if the array-dimenions are compile-time constants, so that probably wouldn't solve the problem your Matrix class is meant to solve.
When you have created 2D array (for example 3x3), you have created 1 array with 3 elements, where each element is pointer to separate array. So to clear memory for this matrix you need to clear 4 arrays (3 rows and 1 array containing pointers).
You can check how many times in your code you are calling new operator
it will be r+1 times
data_ = new int*[r];// 1 time
for (int i = 0; i < r; i++ {
data_[i] = new T[c]; // r times
}
Part I:
The line data_ = new int*[r]; allocates and default initializes a dynamic array of int* through new, so you would need to provide a corresponding delete [] data_; for this line.
Part II:
The line data_[i] = new int[c]; dynamically allocates and default initializes an int array and then the pointer to that first element is returned and stored as the data_[i] element. So here again you would need a corresponding delete [] data_[i]; to get rid of the memory leak.
So these were the reasons why you need two separate delete []. The process is as shown in the screenshot. Also note that the important thing is the default initialization. So the int array elements will not all have a value 0 as wrongly shown in the answer by #Jeremy Friesner.

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)

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

A variable seems to be de-referencing when I use it in a dynamic array (C++)

Here we are once again good people of the internet.
This is the code I'm using:
//This is what is in the header file
int *myArr[]; // A two-dimensional array representing holding the matrix data
//This is what is in the definition file
Matrix::Matrix(int n, int m)
{
myRows = n;
myColumns = m;
initialize();
}
void Matrix::initialize()
{
*myArr = new int[myRows];
for (int i=0; i < 3; i++)//Only set to 3 since myRows is acting crazy
{
myArr[i] = new int[myColumns];
}
}
For some reason when I use myRows variable to create the myArr array it just seems to stop referencing the value it was pointing towards before.
For instance I give it the value 3 and after the *myArr = new int[myRows] has been executed it changes the value of myRows to 9834496, which I don't understand.
Does the "new" de-reference the variable or something?
Or am I doing something wrong?
Oh and since this is a school practice project (so I won't blame you if you don't answer) I would prefer an answer over working code, so that I could know what I did wrong for future projects.
int *myArr[];
This is wrong! You've to tell the compiler the size also, of your array of pointer. How about if you declare int a[]. You're telling the compiler to create an array of int, of unknown size, which is not allowed in C++. That is why you cannot do that.
I would suggest you to do this:
int **myArr;
void Matrix::initialize()
{
myArr = new int*[myRows]; //note int* here!
for (int i=0; i < myRows; i++)
{
myArr[i] = new int[myColumns];
}
}
This should work now.
Try replacing:
*myArr = new int[myRows];
by
myArr = new int*[myRows];
You should use std::vector<>. It deals with all the problems of memory allocation and deallocation.
And it does so without any bugs.
And then you focus yourself on the real goals of your algorithm. Not on memory management :-)
typedef std::vector<int> Ints;
typedef std::vector<Ints> Matrix;
Matrix myArray;
I'm not sure if you're project requires you to use multi-level pointers, if it doesn't another way you can approach this problem is to just treat the multi-dimensional array as one big flat array.
That means when you reach the end of a row, the index after that would be the first element of the next row. Here's how the code might look:
// In this approach the double pointer int**
// is replaced with just a simple int*
int *myArr;
// Here's your Matrix ctor. Note the use of the initializer list
Matrix::Matrix(int n, int m) : myRows(n), myColumns(m)
{
initialize();
}
void Matrix::initialize()
{
myArr = new int[myRows * myColumns];
/* This loop is no longer needed since we're allocating
one big chunk at once.
for (int i=0; i < 3; i++)//Only set to 3 since myRows is acting crazy
{
myArr[i] = new int[myColumns];
}
*/
}
// To retrieve stuff from your array
// you would do something like this:
int Matrix::operator() (const int x, const int y)
{
return myArr[x * myRows + y];
}