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!
}
}
Related
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;
#include < vector >
using namespace std;
class Rclass
{
public:
vector<int> ir0T;
vector<int> ir1T;
private:
int f();
}
int Rclass::f()
{
ir0T.clear();
ir1T.clear();
ir0T.push_back(1);
ir1T.push_back(2);
}
this throws error
"Rclass.cpp:90: error: member function 'clear' not viable: 'this' argument has type 'const vector', but function is not marked const
ir0T.clear();
^~~~"
Rclass.cpp:91: error: member function 'clear' not viable: 'this' argument has type 'const vector', but function is not marked const
ir1T.clear();"
why?
^~~~
I tried adding "const vector ir0T;"
You cannot set the matrix member variable to a local varable created in a local member function - the local variable will be destroyed when the function ends and then the matrix member variable won't be pointing to anything. So instead, if you insist on using a raw pointer, use calloc() because it allocates the memory like malloc and then it sets it all to zero. The main problem with this is that then you need a copy constructor, assignment operator and destructor - That's not the way to go if you can help it. It would be better to use a std::vector<std::vector<int>> because all the dynamic allocation and deallocation is hidden from you. Plus you can reserve the size if you know it ahead of time. How to initializ the "vector"-ized version to zero can be seen here: Initializing a two dimensional std::vector
#include <vector>
class CS
{
private:
std::vector<std::vector<int> > Rightalpha;
public:
void CreateMtrx(int a, int b)
{
// Defaults to zero initial value
Rightalpha = std::vector<std::vector<int> >(a, std::vector<int>(b));
}
};
int main()
{
CS cs;
cs.CreateMtrx(4,4);
return 0;
};
A better alternative if it is fixed and you know ahead of time how big the matrix is: you can just use a plain array directly as a member variable instead of using a pointers to dynamically allocated memory. If the matrix is small (like 4x4) this will give you cache locality and a performance improvement. Plus if you are using c++11 you can clear the array at the declaration and you don't need a CreateMatrix() member variable at all - something like this:
class CS
{
private:
int Rightalpha[4][4] = {};
};
int main()
{
CS cs;
return 0;
};
Or like one of the comments suggested you could use std::array instead of a plain array, if you want a nice STL-like interface to the array. There are some advantages listed here: Replace fixed size arrays with std::array?
Firstly a few fundamentals.
When CreateMtrx() returns Rightalpha will become invalid as a will destruct.
And I would recommend using lower camel case naming for variables and upper camel case for types. i.e. rightAlpha instead of Rightalpha, to avoid confusion with types.
As for your actual question you can initialise a 2D array with a nested loop:
for(unsigned int i = 0; i < 4; i++)
{
for(unsigned int j = 0; j < 4; j++)
{
rightAlpha[i][j] = 0;
}
}
Finally, when asking for help 'craps up' is not conducive to constructive answers. It is important to be clear on what your expected behaviour is and what results you are actually seeing.
If Rightalpha is a data member of your class it doesn't need to be an int**. You probably just want it to be an int[4][4] and skip using a local variable 'a' in your create function.
If you really want it to be a pointer, just make it an int*, and use it with 2D-array syntax. Instead of: int a[4][4]; Do: int* a = new [4*4];
I see from the comment that you can't change the type of Rightalpha. You will then need to do manual memory management. You will need to initialize you int** with the new operator.
You will need to allocate each array in the 2D array.
rightAlpha = new int*[4];
for (int i = 0 ; i < 4 ; i++) {
rightAlpha[i] = new int[4];
}
You can read more about initialisation of a multi-dimentional arrays here:
How do I declare a 2d array in C++ using new?
Even if that works, you will need to free and manage memory and deal carefully with all the pitfalls of manual memory management. That's why I strongly suggest to use a std::vector<int>:
struct CS {
createMatrix() {
rightAlpha = std::vector<int>(4*4);
}
private:
std::vector<int> rightAlpha;
With this solution, you don't need to worry about memory stuff as the std::vector will do it for you.
If you need matrix semantics, you can add a function that returns the right element according to a j i position.
int operator()(int i, int j) const {
return rightAlpha[j+4*i];
}
It may be used like this:
CS myCs;
myCs(3, 2);
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.
first question:
for known dimensions, we don't need new/malloc for the creation
const int row = 3;
const int col = 2;
int tst_matrix[row][col] ={{1,2},{3,4},{5,6}}
however, there is no easy to pass this two-dimensional array to another function, right? because
int matrix_process(int in_matrix[][])
is illegal, you have to specify all the dimensions except the first one. if I need to change the content of in_matrix, how could I easily pass tst_matrix to the function matrix_process?
second question:
what's the standard way to create 2-dimensional array in c++ with new? I dont wanna use std::vector etc.. here.
here is what I come up with, is it the best way?
int **tst_arr = new int*[5];
int i=0, j=0;
for (i=0;i<5;i++)
{
tst_arr[i] = new int[5];
for (j=0;j<5;j++)
{
tst_arr[i][j] = i*5+j;
}
}
In addition, if I pass tst_array to another function, like:
int change_row_col( int **a)
{
.....................
//check which element is 0
for (i=0; i<5; i++)
for(j=0;j<5;j++)
{
if (*(*(a+i)+j)==0) //why I can not use a[i][j] here?
{
row[i]=1;
col[j]=1;
}
}
.....................
}
In addition, if I use ((a+i)+j), the result is not what I want.
Here is the complete testing code I had:
#include <iostream>
using namespace std;
//Input Matrix--a: Array[M][N]
int change_row_col( int **a)
{
int i,j;
int* row = new int[5];
int* col = new int[5];
//initialization
for(i=0;i<5;i++)
{
row[i]=0;
}
for(j=0;j<5;i++)
{
col[j]=0;
}
//check which element is 0
for (i=0; i<5; i++)
for(j=0;j<5;j++)
{
if (*(*(a+i)+j)==0) //why I can not use a[i][j] here?
{
row[i]=1;
col[j]=1;
}
}
for(i=0;i<5;i++)
for (j=0;j<5;j++)
{
if (row[i] || col[j])
{
*(*(a+i)+j)=0;
}
}
return 1;
}
int main ()
{
int **tst_arr = new int*[5];
int i=0, j=0;
for (i=0;i<5;i++)
{
tst_arr[i] = new int[5];
for (j=0;j<5;j++)
{
tst_arr[i][j] = i*5+j;
}
}
for (i=0; i<5;i++)
{
for(j=0; j<5;j++)
{
cout<<" "<<tst_arr[i][j];
}
cout<<endl;
}
change_row_col(tst_arr);
for (i=0; i<5;i++)
{
for(j=0; j<5;j++)
{
cout<<" "<<tst_arr[i][j];
}
cout<<endl;
}
for (i=0;i<5;i++)
{
delete []tst_arr[i];
}
delete []tst_arr;
}
For multidimensional arrays were all the bounds are variable at run time, the most common approach that I know of is to use a dynamically allocated one dimensional array and do the index calculations "manually". In C++ you would normally use a class such as a std::vector specialization to manage the allocation and deallocation of this array.
This produces essentially the same layout as a multidimensional array with fixed bounds and doesn't have any real implied overhead as, without fixed bounds, any approach would require passing all bar one of the array dimensions around at run time.
I honestly think the best idea is to eschew raw C++ arrays in favor of a wrapper class like the boost::multi_array type. This eliminates all sorts of weirdness that arises with raw arrays (difficulty passing them S parameters to functions, issues keeping track of the sizes of the arrays, etc.)
Also, I strongly urge you to reconsider your stance on std::vector. It's so much safer than raw arrays that there really isn't a good reason to use dynamic arrays over vectors in most circumstances. If you have a C background, it's worth taking the time to make the switch.
My solution using function template:
template<size_t M,size_t N>
void Fun(int (&arr)[M][N])
{
for ( int i = 0 ; i < M ; i++ )
{
for ( int j = 0 ; j < N ; j++ )
{
/*................*/
}
}
}
1)
template < typename T, size_t Row_, size_t Col_>
class t_two_dim {
public:
static const size_t Row = Row_;
static const size_t Col = Col_;
/* ... */
T at[Row][Col];
};
template <typename T>
int matrix_process(T& in_matrix) {
return T::Row * T::Col + in_matrix.at[0][0];
}
2) use std::vector. you're adding a few function calls (which may be inlined in an optimized build) and may be exporting a few additional symbols. i suppose there are very good reasons to avoid this, but appropriate justifications are sooooo rare. do you have an appropriate justification?
The simple answer is that the elegant way of doing it in C++ (you tagged C and C++, but your code is C++ new/delete) is by creating a bidimensional matrix class and pass that around (by reference or const reference). After that, the next option should always be std::vector (and again, I would implement the matrix class in terms of a vector). Unless you have a very compelling reason for it, I would avoid dealing with raw arrays of arrays.
If you really need to, but only if you really need to, you can perfectly work with multidimensional arrays, it is just a little more cumbersome than with plain arrays. If all dimensions are known at compile time, as in your first block this are some of the options.
const unsigned int dimX = ...;
const unsigned int dimY = ...;
int array[dimY][dimX];
void foo( int *array[dimX], unsigned int dimy ); // [1]
void foo( int (&array)[dimY][dimX] ); // [2]
In [1], by using pass-by-value syntax the array decays into a pointer to the first element, which means a pointer into an int [dimX], and that is what you need to pass. Note that you should pass the other dimension in another argument, as that will be unknown by the code in the function. In [2], by passing a reference to the array, all dimensions can be fixed and known. The compiler will ensure that you call only with the proper size of array (both dimensions coincide), and thus no need to pass the extra parameter. The second option can be templated to accomodate for different sizes (all of them known at compile time):
template <unsigned int DimX, unsigned int DimY>
void foo( int (&array)[DimY][DimX] );
The compiler will deduct the sizes (if a real array is passed to the template) and you will be able to use it inside the template as DimX and DimY. This enables the use of the function with different array sizes as long as they are all known at compile time.
If dimensions are not known at compile time, then things get quite messy and the only sensible approach is encapsulating the matrix in a class. There are basically two approaches. The first is allocating a single contiguous block of memory (as the compiler would do in the previous cases) and then providing functions that index that block by two dimensions. Look at the link up in the first paragraph for a simple approach, even if I would use std::vector instead of a raw pointer internally. Note that with the raw pointer you need to manually manage deletion of the pointer at destruction or your program will leak memory.
The other approach, which is what you started in the second part of your question is the one I would avoid at all costs, and consists in keeping a pointer into a block of pointers into integers. This complicates memory management (you moved from having to delete a pointer into having to delete DimY+1 pointers --each array[i], plus array) and you also need to manually guarantee during allocation that all rows contain the same number of columns. There is a substantial increase in the number of things that can go wrong and no gain, but some actual loss (more memory required to hold the intermediate pointers, worse runtime performance as you have to double reference, probably worse locality of data...
Wrapping up: write a class that encapsulates the bidimensional object in terms of a contiguous block of memory (array if sizes are known at compile time --write a template for different compile time sizes--, std::vector if sizes are not known until runtime, pointer only if you have a compelling reason to do so), and pass that object around. Any other thing will more often than not just complicate your code and make it more error prone.
For your first question:
If you need to pass a ND array with variable size you can follow the following method to define such a function. So, in this way you can pass the required size arguments to the function.
I have tested this in gcc and it works.
Example for 2D case:
void editArray(int M,int N,int matrix[M][N]){
//do something here
}
int mat[4][5];
editArray(4,5,mat); //call in this way
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];
}