Multi-dimensional array and pointers in C++? - c++

int *x = new int[5]();
With the above mentality, how should the code be written for a 2-dimensional array - int[][]?
int **x = new int[5][5] () //cannot convert from 'int (*)[5]' to 'int **'
In the first statement I can use:
x[0]= 1;
But the second is more complex and I could not figure it out.
Should I use something like:
x[0][1] = 1;
Or, calculate the real position then get the value
for the fourth row and column 1
x[4*5+1] = 1;

I prefer doing it this way:
int *i = new int[5*5];
and then I just index the array by 5 * row + col.

You can do the initializations separately:
int **x = new int*[5];
for(unsigned int i = 0; i < 5; i++)
x[i] = new int[5];

There is no new[][] operator in C++. You will first have to allocate an array of pointers to int:
int **x = new int*[5];
Then iterate over that array. For each element, allocate an array of ints:
for (std::size_t i = 0; i < 5; ++i)
x[i] = new int[5];
Of course, this means you will have to do the inverse when deallocating: delete[] each element, then delete[] the larger array as a whole.

This is how you do it:
int (*x)[5] = new int[7][5] ;
I made the two dimensions different so that you can see which one you have to use on the lhs.

Ff the array has predefined size you can write simply:
int x[5][5];
It compiles
If not why not to use a vector?

There are several ways to accomplish this:
Using gcc's support for flat multidimensional arrays (TonyK's answer, the most relevant to the question IMO). Note that you must preserve the bounds in the array's type everywhere you use it (e.g. all the array sizes, except possibly the first one), and that includes functions that you call, because the produced code will assume a single array. The allocation of $ new int [7][5] $ causes a single array to be allocated in memory. indexed by the compiler (you can easily write a little program and print the addresses of the slots to convince yourself).
Using arrays of pointers to arrays. The problem with that approach is having to allocate all the inner arrays manually (in loops).
Some people will suggest using std::vector's of std::vectors, but this is inefficient, due to the memory allocation and copying that has to occur when the vectors resize.
Boost has a more efficient version of vectors of vectors in its multi_array lib.
In any case, this question is better answered here:
How do I use arrays in C++?

Related

How to get the dimensions of a 2d dynamic array of strings in C++?

I have a dynamically populated array of strings in C++:
string** A;
it is populated like this:
A = new string*[size1];
and then:
for (unsigned int i = 0; i < size1; i++)
{
A[i] = new string[size2];
for (unsigned int j = 0; j < size2; j++)
{
A[i][j] = whatever[j];
}
}
elsewhere, I want to find out the dimensions (size1 and size2).
I tries using this:
sizeof(A[i]) / sizeof(A[i][0])
but it doesn't work.
Any ideas ?
Thanks
When you allocate memory via new T[N], the value N is not stored anywhere . If you need to know it later, you will need to keep track of it in your code.
There are pre-existing classes for allocating memory that also remember the length that was allocated. In your code:
vector<vector<string>> A(size1, vector<string>(size2));
// (code to populate...)
then you can access A.size() to get size1, and A[0].size() to get size2.
If the dimensions are known at compile-time you may use array instead of vector.
It is very simple to find the size of a two dimensional (more exactly of one-dimensional dynamically allocated arrays) array. Just declare it like
std::vector<std::vector<std::string>> A;
and use
std::cout << A.size() << std::endl;
As for your approach then you have to store the sizes in some variables when the array is allocated.
If you are learning C++, I would recommend that you learn Classes. With a class you can encapsulate int variables along with your 2D array that you can use to store the dimensions of your array. For example:
class 2Darray{
string **array;
int rows;
int cols;
}
You can then get the dimensions of your 2Darray object anytime by reading these member variables.
vectors will do this for you behind the scenes but its good for you to learn how to do this.
You can't create an array just using pointer operator. Every array is basically a pointer with allocated memory. That's why compiler wants constant before creating array.
Basically; sizeof(A[i]) won't give you the size of array. Because sizeof() function will return the a pointers size which is points to A[i] location. sizeof(A[i]) / sizeof(A[i][1]) will probably give you 1 because you are basically doing sizeof(int)/sizeof(int*)
So you need to store the boundary yourself or use vectors. I would prefer vectors.
Can't get array dimensions through pointer(s)

How to allocate memory for a static n-dimensional array in c++

What is the best way to allocate memory for an n-dimensional array in c++ at runtime? I am trying to read a matrix of values from a file, and depending on which file I read, the matrix could be any size. However, once the matrix is created, its size is static.
Since I don't know at compile-time what the size will be, I can't define it as int[a][b], so I was experimenting with using pointers to pointers like int**, but when I declare int** arr; arr[0][0] = 1 I get an error. I've experimented with other solutions as well. For example, I tried using one of the answers to Determine array size in constructor initializer, using int* arr; arr = new int[a], but it doesn't seem to work once I try to use it for two dimensions. Granted, I could be using it incorrectly, but the following block of code gives me a segfault:
int** arr;
(*arr) = new int[a];
edit: And of course, right after I ask the question, I find something semi-suitable in Need help regarding Dynamic Memory Allocation for two dimensional arrays in C++. I'd prefer not to do it this way, but it's definitely doable.
You would do it something like this (stolen from this answer):
int** ary = new int*[sizeX];
for(int i = 0; i < sizeX; ++i)
ary[i] = new int[sizeY];
Alternatively, you can do this:
int *ary = new int[sizeX*sizeY];
// ary[i][j] is then rewritten as
ary[i*sizeY+j]
It might remove the headache of pointer indirection.

Incrementally dynamic allocation of memory in C/C++

I have a for-loop that needs to incrementally add columns to a matrix. The size of the rows is known before entering the for-loop, but the size of the columns varies depending on some condition. Following code illustrates the situation:
N = getFeatureVectorSize();
float **fmat; // N rows, dynamic number of cols
for(size_t i = 0; i < getNoObjects(); i++)
{
if(Object[i] == TARGET_OBJECT)
{
float *fv = new float[N];
getObjectFeatureVector(fv);
// How to add fv to fmat?
}
}
Edit 1 This is how I temporary solved my problem:
N = getFeatureVectorSize();
float *fv = new float[N];
float *fmat = NULL;
int col_counter = 0;
for(size_t i = 0; i < getNoObjects(); i++)
{
if(Object[i] == TARGET_OBJECT)
{
getObjectFeatureVector(fv);
fmat = (float *) realloc(fmat, (col_counter+1)*N*sizeof(float));
for(int r=0; r<N; r++) fmat[col_counter*N+r] = fv[r];
col_counter++;
}
}
delete [] fv;
free(fmat);
However, I'm still looking for a way to incrementally allocate memory of a two-dimensional array in C/C++.
To answer your original question
// How to add fv to fmat?
When you use float **fmat you are declaring a pointer to [an array of] pointers. Therefore you have to allocate (and free!) that array before you can use it. Think of it as the row pointer holder:
float **fmat = new float*[N];
Then in your loop you simply do
fmat[i] = fv;
However I suggest you look at the std::vector approach since it won't be significantly slower and will spare you from all those new and delete.
better - use boost::MultiArray as in the top answer here :
How do I best handle dynamic multi-dimensional arrays in C/C++?
trying to dynamically allocate your own matrix type is pain you do not need.
Alternatively - as a low-tech, quick and dirty solution, use a vector of vectors, like this :
C++ vector of vectors
If you want to do this without fancy data structures, you should declare fmat as an array of size N of pointers. For each column, you'll probably have to just guess at a reasonable size to start with. Dynamically allocate an array of that size of floats, and set the appropriate element of fmat to point at that array. If you run out of space (as in, there are more floats to be added to that column), try allocating a new array of twice the previous size. Change the appropriate element of fmat to point to the new array and deallocate the old one.
This technique is a bit ugly and can cause many allocations/deallocations if your predictions aren't good, but I've used it before. If you need dynamic array expansion without using someone else's data structures, this is about as good as you can get.
To elaborate the std::vector approach, this is how it would look like:
// initialize
N = getFeatureVectorSize();
vector<vector<float>> fmat(N);
Now the loop looks the same, you access the rows by saying fmat[i], however there is no pointer to a float. You simply call fmat[i].resize(row_len) to set the size and then assign to it using fmat[i][z] = 1.23.
In your solution I suggest you make getObjectFeatureVector return a vector<float>, so you can just say fmat[i] = getObjectFeatureVector();. Thanks to the C++11 move constructors this will be just as fast as assigning the pointers. Also this solution will solve the problem of getObjectFeatureVector not knowing the size of the array.
Edit: As I understand you don't know the number of columns. No problem:
deque<vector<float>> fmat();
Given this function:
std::vector<float> getObjectFeatureVector();
This is how you add another column:
fmat.push_back(getObjectFeatureVector());
The number of columns is fmat.size() and the number of rows in a column is fmat[i].size().

initialize an int[][] with new()

I am a c++ newbie. While learning I came across this.
if I have a pointer like this
int (*a)[2][3]
cdecl.org describe this as declare a as pointer to array 2 of array 3 of int:
When I try
int x[2][3];
a = &x;
this works.
My question is how I can initialize a when using with new() say something like
a = new int [] [];
I tried some combinations but doesn't get it quite right.
Any help will be appreciated.
You will have to do it in two steps - first allocate an array of pointers to pointers(dynamically allocated arrays) and then, allocate each of them in turn. Overall I believe a better option is simply to use std::vector - that is the preferred C++ way of doing this kind of things.
Still here is an example on how to achieve what you want:
int a**;
a = new int*[2];
for (int i =0; i< 2;++i){
a[i] = new int[3]
}
... use them ...
// Don't forget to free the memory!
for (int i = 0; i< 2; ++i) {
delete [] a[i];
}
delete [] a;
EDIT: and as requested by Default - the vector version:
std::vector<std::vector<int> > a(2, std::vector<int>(3,0));
// Use a and C++ will take care to free the memory.
It's probably not the answer you're looking for, but what you
need is a new expression whose return type is (*)[2][3] This
is fairly simple to do; that's the return type of new int
[n][2][3], for example. Do this, and a will point to the
first element of an array of [2] of array of [3] int. A three
dimensional array, in sum.
The problem is that new doesn't return a pointer to the top
level array type; it returns a pointer to the first element of
the array. So if you do new int[2][3], the expression
allocates an array of 2 array of 3 int, but it returns
a pointer to an array of 3 int (int (*a)[3]), because in C++,
arrays are broken (for reasons of C compatibility). And there's
no way of forcing it to do otherwise. So if you want it to
return a pointer to a two dimensional array, you have to
allocate a three dimensional array. (The first dimension can be
1, so new [1][2][3] would do the trick, and effectively only
allocate a single [2][3].)
A better solution might be to wrap the array in a struct:
struct Array
{
int data[2][3];
};
You can then use new Array, and everything works as expected.
Except that the syntax needed to access the array will be
different.

dynamic allocation of rows of 2D array in c++

In c++, I can create a 2D array with fixed number of columns, say 5, as follows:
char (*c)[5];
then I can allocate memory for rows as follows
c = new char[n][5];
where n can be any variable which can be assigned value even at run time. I would like to know whether and how can I dynamically allocate variable amount of memory to each row with this method. i.e. I want to use first statement as such but can modify the second statement.
Instead of a pointer to an array, you'd make a pointer to a pointer, to be filled with an array of pointers, each element of which is in turn to be filled with an array of chars:
char ** c = new char*[n]; // array of pointers, c points to first element
for (unsigned int i = 0; i != n; ++i)
c[i] = new char[get_size_of_array(i)]; // array of chars, c[i] points to 1st element
A somewhat more C++ data structure would be a std::vector<std::string>.
As you noticed in the comment, dynamic arrays allocated with new[] cannot be resized, since there is no analogue of realloc in C++ (it doesn't make sense with the object model, if you think about it). Therefore, you should always prefer a proper container over any manual attempt at dynamic lifetime management.
In summary: Don't use new. Ever. Use appropriate dynamic containers.
You need to declare c as follows: char** c; then, allocate the major array as follows: c = new char*[n]; and then, allocate each minor array as follows: c[i] = new char[m]
#include <iostream>
using namespace std;
main()
{
int row,col,i,j;
cout<<"Enter row and col\n";
cin>>row>>col;
int *a,(*p)[col]=new (int[row][col]);
for(i=0;i<row;i++)
for(j=0;j<col;j++)
p[i][j]=i+j;
for(i=0;i<row;i++)
for(j=0;j<col;j++)
cout<<i<<" "<<j<<" "<<p[i][j]<<endl;
//printf("%d %d %d\n",i,j,p[i][j]);
}