2D array of structures with new keyword in C++! - c++

I have a structure defined in a file called 'xxx.h':
struct struct_name
{
declarations;
};
I included this header - 'xxx.h' - in another c++ file, yyy.cpp
And then I try to create a 2D array of the above structure using new keyword as follows (I learnt how to create a 2D array of structures from this link: Declaring a 2D array of type struct in c++).
struct struct_name * some_name;
some_name = new struct struct_name[x][y];
When I compile, I get the following error: error: ‘y’ cannot appear in a constant-expression. This error particularly points to the second dimension of the array.
Also When I tried to initialize this 2D array of structures with some value like:
some_name[i][j].var_name = value;
I get the following error:
error: no match for ‘operator[]’ in ‘*(some_name + ((sizetype)(((unsigned int)i) * 12u)))[j]’
Please advise me how to fix this.
Thanks.

In the interest of getting you up and running as quickly as possible, I'm going to belay the usual memory layout diatribe and simply tell you one way to get your situation resolved.
The reason you're error is happening is because C++ requires knowledge of types when declaring an array, allocating an array, etc. When you do this:
some_name = new struct_name[x][y];
what you're telling the compiler is "I want to allocate x objects of type struct_name[y]". But struct_name[y] isn't a type known at compile-time. The size is unknown, but must be known (thus the error about a constexpr expectations. This would work:
struct_name (*some_name)[WIDTH] = new struct_name[x][WIDTH];
would work if WIDTH is a compile-time known-constant. But for you, that isn't constant so another solution is required.
Altnerative Approach
An alternative quick-fix approach is presented below
#include <vector>
int main()
{
int rows, cols;
// get row and column count.
typedef std::vector<struct_name> MatrixRow;
typedef std::vector<MatrixRow> Matrix;
Matrix some_name(rows, MatrixRow(cols));
// use some_name[i][j] however you need
return 0;
}
There are other ways to do this, but this is likely the fastest way to get you running. Further, it promotes proper RAII concepts. If you need a more specialized purpose of a 2D matrix you may have to develop your own class, as the C++ standard library has no direct 2D dynamic array concept natively, thus why we invent it using a vector of vector-types.

Try the declaration within yyy.cpp as:
struct struct_name **some_name;
The reason for this is that some_name[i] needs to be of type struct_name * in order to access another level of variables.

Do you really need a c++ arrays?
Why not use std::vector<std::vector<struct_name>> ?
If you don't need dynamic allocation then you could use:
std::array<std::array<struct_name, 2>, 3> where 2 and 3 are the sizes of your 2D array.

Related

create a Dynamic std::array of std::array

My task requires me to create an array of arrays to store some data , where the number of row is fixed and the columns are to be decided at run-time.
If I was using a simple int array then this would've been a simple task but because I have to use std::array , I am lost .
My attempt so far
#include<iostream>
#include<array>
using std::array;
int main(){
array<array<int,1>*,3> x;
for(size_t i=0;i<3;i++)
{
x[i][0]=array<int,3>;
}
}
which leads to the error
array1.cpp:12:29: error: expected '(' for function-style cast or type
construction
x[i][0]=array;
~~~~~~~~~~~~^ 1 error generated.
when using clang++
I have read that an std::array is equivalent to a normal array ,
I know i can use vectors but since i know how many rows i have from the beginning , I feel it to be a waste to use vectors , while I would love the added functionality of std::array when compared to a traditional array. How do I implement this .
std::array<std::vector<int>,3> is the type you want.
std::vector is a dynamicly sized array.
int main(){
std::array<std::vector<int>,3> x;
for(std::size_t i=0;i<3;i++)
{
x[i]=std::vector<int>(22);
}
}
this creates a 3 "major" element array of 22 "minor" size.
Note that column-major and row-major (which is first and which is second) is a matter of convention. So std::vector<std::array<3,int>> is another equally valid interpretation of the requirements.
If you are banned from using std::vector, you will have to figure out an alternative solution, possibly rolling your own. I'd advise against unique_ptr<int[]> (or worse, raw pointers) as they don't store the size of the element.
A std::array< std::array< cannnot be dynamic in either dimension. std::array is fixed size.
My task requires me to create an array of arrays to store some data , where the number of row is fixed and the columns are to be decided at run-time.
It sounds like your task requires using a matrix class. Like boost::numeric::ublas::matrix.
The benefit of using a matrix class is that internally it uses one dynamic array to minimize storage overhead.
If you are coding this as an exercise create your own matrix class. Otherwise use an existing one.

error : no match for 'operator[]'

I am solving a problem in which I m trying to pass address a 2-D array of a structure and trying to manipulate it but, whenever I use [] operator to access the array elements , I get a compile time error:
no match for 'operator[]'
in my codeblocks IDE.
#include <iostream>
using namespace std;
typedef struct mat
{
int data;
int flag;
} cell;
int mat(cell *);
int main()
{
int m,n;
cin>>m>>n;
cell game[n][m];
cout<<"The length of matrix is "<<mat(&game[0][0]);
}
int mat(cell *arr)
{
return (sizeof(arr[0])/sizeof(arr[0][0]));
}
cell game[n][m];
This is not legal C++. You are using a compiler-specific extension. At this point I advise you against using any compiler-specific extensions. Use standard C++ only. In standard C++ there are no Variable Length Arrays. Don't use arrays in your C++ programs. To get proper variable length array functionality. You should use std::vector instead, like this:
std::vector<std::vector<cell>> game;
Further,
&game[0][0]
is not an address of a 2D array. This is an address of the first element in the array. It contains no information about the number of elements. It is lost forever. You cannot pass it to some function and expect the size of the array to be recovered. To get proper array functionality with a built-in size function, use std::vector.
Last but not least,
(sizeof(arr[0])/sizeof(arr[0][0]));
arr is a cell*. arr[0] is a cell. arr[0][0] is invalid because a cell is neither an array not a pointer, nor it has a custom [] operator defined. In any case you cannot use sizeof to recover the number of elements in the array from a pointer to its first element. To get proper array functionality with a built-in size function, use std::vector.
Two things:
Your function takes a pointer to cell but since you're treating it like a 2D array, you should probably change your signature to either accept a cell ** arr or a cell arr[m][] where m is the (fixed) size of the array and must be specified. Note that these data structures have fundamentally different representations in memory - they just have the same [][] syntax for accessing elements.
You can't use the sizeof function to determine the length of an array if you pass it as a pointer to an elem. You will need to pass the dimensions along with your array, like this:
int mat(cell **arr, int m, int n);
The definition being given basically says that your class doesn't define the operator [], meaning you can't use the syntax you are trying to use.

CUDA C++: declare a vector with length

I recently found this won't work in my global CUDA C++ code that I plan to compile and later to be called in Matlab:
int M = 10; float V[M];
or if I were to import M value from the matlab host code.
But this works:
float V[10];
I was told there exists a function called new that I can use to avoid this problem, but I read online and am still quite confused how to use this new function, and it seems only to apply to host code, is that right? If so, it won't apply to my case then, since my host code is in matlab. Is this a way to get around this, so that I don't have to change vector lengths one by one? Thank you!
I don't know anything about MATLAB or CUDA, but your problem is in C++. Arrays declared like that must have sizes fixed at compile-time.
Solution 1: Fix the size
Declare your variable M const. These are equivalent:
int const M = 10;
const int M = 10;
The compiler would then know that it can assume these variables will always have the same value no matter how you run the program.
Solution 2: C-style dynamic allocation
Dynamic allocation with new and delete. Arrays allocated on the abstract section of memory called the "free-store" (rather than on the "stack", like those arrays you have) can determine their sizes on the fly. You use it like this:
float * V = new V[M]; //V is a pointer to some freestore memory
//You use it and pass it like you would a normal array:
V[2] = 5.5;
int x = some_func(V);
//But after you're done, you should manually free the memory
delete [] V; //don't forget the [], since you used [] in the allocation
I don't recommend this, because of the possiblity of forgetting to delete the memory.
Solution 3: Automatic memory management with C++'s vector
In C++, the work of memory management can be hidden behind structures called classes.
#include<vector>
using std::vector;
vector<float> V(M); //V is a vector of floats, with initial size M
//You use it like a normal array
V[2] = 5.5;
//But to pass it as an array, you need to pass a pointer to the first element
int x = some_func(&V[0]); //read as &(V[0]): pass in the address of V[0]
Solution 3b: CUDA-compatible vector
Thrust is a C++ template library for CUDA based on the Standard Template Library (STL). Thrust allows you to implement high performance parallel applications with minimal programming effort through a high-level interface that is fully interoperable with CUDA C.
http://docs.nvidia.com/cuda/thrust/#vectors
Conclusion
If you're using fixed sizes, I recommend solution 1. If you're using sizes determined during runtime, I recommend vector.
(By the way, when you pass an ordinary array to a function, you are actually passing a pointer to the first element, NOT the array. The name of the array is automatically converted to a pointer type.)

C++ - How do I put a static array inside my array?

I apologize for the total noob question, but I just cannot find an answer. I googled, searched here, searched C++ array documentation, and some C++ array tutorials.
The question is simple. Why does
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
short pixelarray[3][3] = {{1,1,1},{0,0,0},{-1,-1,-1}};
... //do stuff. Imagine a loop here, and BIG array - I'm just simplifying it for StackOverflow
pixelarray = {{1,0,-1},{1,0,-1},{1,0,-1}};
return 0;
}
result in an error?
1>arraytest.cpp(11): error C2059: syntax error : '{'
How do I put a static array inside my array? I realize I could set each item individually, but there has to be a better way.
Built-in arrays in C++ have their problems, and not being assignable does make them rather inflexible. I'd stick with std::array, a C++11 container that emulates a better style of array, which allows a somewhat similar syntax to what you're looking for:
std::array<int, 3> arr{{1, 2, 3}};
std::array<int, 3>{{4, 5, 6}}.swap(arr);
//now arr is {4, 5, 6}
Here's a full sample. The trick is to use the initializer list on a newly-constructed array and then swap that with yours. I believe that the next C++ update is going to remove the need for the double braces as well, which makes it an even closer match to familiar syntax.
Initializer lists can be used just for initialization :)
Like when you declare your variable:
short pixelarray[3][3] = {{1,1,1},{0,0,0},{-1,-1,-1}}; // this is ok
You have to remove this:
pixelarray = {{1,0,-1},{1,0,-1},{1,0,-1}};
And assign new values manually (i.e. pixelarray[x][y] = or with a memcpy(pixelarray, <some other array>, sizeof(pixelarray)))
If you don't want to assign each individual element manually, you can do this:
short pixelarray2[3][3] = {{1,0,-1},{1,0,-1},{1,0,-1}};
memcpy(pixelarray, pixelarray2, sizeof(pixelarray));
As #Nick points out: initializer lists are not for assignment.
Arrays are not assignable, so the short answer is that you can't do exactly what you're asking for. The most direct way to do something similar enough for most purposes is probably a 2D array class that acts as a wrapper around a std::vector, on the order of the one I posted in a previous answer.
If you insist on staying with C-style arrays, one possibility would be to use a pointer:
int main() {
typedef short array[3];
array pixelarray0[3] = {{1,1,1},{0,0,0},{-1,-1,-1}};
array pixelarray1[3] = {{1,0,-1},{1,0,-1},{1,0,-1}};
array *pixelarray = pixelarray0;
// when needed:
pixelarray = pixelarray1;
}
Taking this question from a straight C context, you can have different constant arrays and just copy them with memcpy:
typedef short TArray[3][3];
const TArray a1 = {{1,1,1},{0,0,0},{-1,-1,-1}};
const TArray a2 = {{1,0,-1},{1,0,-1},{1,0,-1}};
// ...
TArray a;
memcpy( a, a2, sizeof(TArray));
Or you could exploit C99 struct copying, but I'd consider this a dangerous hack because the structure might be padded to be larger than the array, or have a different alignment.
typedef struct {
TArray arr;
} TDummyArray;
// ...
TArray a;
*(TDummyArray*)a = *(TDummyArray*)a2;
Once you have declared your array there is no way to use the assignment operator to reassign the entire content of the array.
So to change the contents or your array after this:
short pixelarray[3][3] = {{1,1,1},{0,0,0},{-1,-1,-1}};
You need to either loop through the array and manually change each value, or you something like std::memcpy to copy your new values over.
But you should really not be using an array in the first place, use some fromthing the std collections library instead like std::array or std::vector. Only use arrays if you have a really really good reason why you can't use a collection.

Trouble placing int matrix array in a C++ Object

I need a variable which will hold 22 pairs of ints (positions in a grid) so I was thinking of having a matrix array. So in my header file is:
int points[22][2];
but when I put the following in the constructor of the object:
this->points = {{1,2},{2,3},...};
It says "must be a expression must be a modifiable lvalue" I've tried using the const keyword and making it a pointer in the header file as described here Expression must be a modifiable L-value
I've also tried creating a separate 2d array and then assigning it but this doesn't work either.
int points2 = {{1,2},{2,3},...};
this->points = points2;
I'm used to Java and I'm not too experienced with C++. There is a default constructor that will assign the values as above and a constructor which will have the matrix as parameter.
The following does work:
this->point[1][1] = 4;
But this means I can't pass another value as a parameter and I end up with 44 lines of messy code in the default constructor! And I was going to use a struct with 2 ints and put them in a vector put that seems like a bit of an overkill and would mean I need 22 vector inserts before I even called the constructor with the manual values and I just thought there must be a better way :)
Thanks
Since you're using C++, a much better choice would be to use a vector of pairs of ints.
Declare it like this:
std::vector<std::pair<int, int> > points;
In your constructor you can specify size at initialization
: points(22),
or set it at any point like this:
points.resize(22);
You can access individual coordinates with
points[1].first = 1;
points[1].second = 44;
or with
points[1] = make_pair(1, 44);
or you can build it up without having to worry about exceeding its allocated size with
points.push_back(make_pair(1, 44));
etc
The fundamental cause of your problem is that arrays do not count as real values in C++. They are substandard in many ways- one of which you have just encountered. Any normal type would work as you expect. Unfortunately, to those of us who are not language experts, the error Visual Studio throws is incredibly unhelpful.
You must create an array on the stack and then manually loop through and assign all the values.