So, I have declared a typedef as:
typedef float Matrix4[4][4];
when I try to Initialize it as:
void getXRotationMatrix(float theta, Matrix4 ans) {
ans = { {0,0,0,0},{1,1,1,1},{0,0,0,0},{1,1,1,1} };
}
it gives an error:
too many initializer values
however, it works when I initialize it as:
void getXRotationMatrix(float theta, Matrix4 ans) {
float a[4][4] = { {0,0,0,0},{1,1,1,1},{0,0,0,0},{1,1,1,1} };
ans = a;
}
It doesn't give any error. Can someone please explain?
when I try to Initialize it as: ans = { {0,0,0,0},{1,1,1,1},{0,0,0,0},{1,1,1,1} };
Note that
ans = { {0,0,0,0},{1,1,1,1},{0,0,0,0},{1,1,1,1} };
is an assignment and not an initialization. On the other hand,
float a[4][4] = { {0,0,0,0},{1,1,1,1},{0,0,0,0},{1,1,1,1} };
is an initialization and so works.
The correct way to initialize ans would be:
Matrix4 ans{ {0,0,0,0},{1,1,1,1},{0,0,0,0},{1,1,1,1} };
Also note that array assignment is not possible in C++.
There is also the concept of type decay that you have to take care(into account) for ans = a;. In particular, both ans and a are actually pointers and so when you write
ans = a;
you're actually assigning one pointer to another instead of one array to another.
You can use a std::vector as follows:
typedef std::vector<std::vector<float>> Matrix4;
void getXRotationMatrix(float theta, Matrix4 ans) {
ans = { {0,0,0,0},{1,1,1,1},{0,0,0,0},{1,1,1,1} };
}
Error with initialization of 2d arrays in C++
when I try to Initialize it as:
ans = { {0,0,0,0},{1,1,1,1},{0,0,0,0},{1,1,1,1} };
Problem 1: That's not initialisation. That's assignment. Arrays cannot be assigned, but that's irrelevant due to next point.
Problem 2: ans is not an array. Function parameters are never arrays. Although you wrote it as an array, it has been adjusted to be a pointer to the element of the said array type. And the braced-init list that you provided is not a valid right hand argument for assigning a pointer.
however, it works when I initialize it as:
ans = a;
It becomes well-formed because a is a valid expression to assign to the pointer. The array will implicitly convert to a pointer to first element.
But the pointer is local to the function, so that function has no side-effects whatsoever.
I recommend returning instead of attempting to modify the parameter. Now, arrays cannot be returned in C++, but there is a simple solution: You can return class instances, and classes may contain array as a member. There is a class template for such array wrapper in the standard library. It's called std::array. Example:
std::array<float[4], 4>
getXRotationMatrix() {
return {{
{0,0,0,0},
{1,1,1,1},
{0,0,0,0},
{1,1,1,1},
}};
}
I need to implement matrix as a class in C++.
This is my class:
class {
private:
int rows, columns;
int **mat;
};
In the main, I need to start the matrix in the regular way. For example : m[0][0]=1;
I thought to overloading the operator[][] but it is forbidden.
I would like to get some help. thanks.
Instead, you could overload the function call operator (operator()()), to get something like this:
int operator()(int p_row, int p_column);
which is legal and clean. I would allow you to write something like this:
// Create and fill in matrix called 'm'...
int matrixElement = m(0, 0); // get element m[0][0]
// ...
Here is an example of how to overload this operator.
Let's say we have vector<vector<int>> xThe operator [][] is really (ignoring out of bounds) vector<int> b = x[0] then int = b[0] combined into one line. I.e accessing the first array then the subscript operator of the second.
Hope this helps.
You can store the data in a continuous array using std::vector and then supply your own indexing operator which returns a pointer to the beginning of the row.
class Matrix
{
int rows, columns;
std::vector<int> data;
public:
/*...*/
// The overloaded operator[] returns a pointer to the beginning
// of the requested row, which can then be indexed for the column
// without checking the boundaries.
int* operator[](int r){
return &data[r*columns];
}
};
Using a vector of vectors is less efficient because the data gets spread to different memory locations. If you need bounds checking you can wrap the pointer in your own class and overload its operator[].
I have several two dimensional arrays of various, differing lengths:
int Array_A[][2] = {{...}, {...}, {...}, ...};
int Array_B[][2] = {{...}, {...}, ...};
int Array_C[][2] = {{...}, ...};
I need another array which allows me to access these arrays:
??? Full_Array[] = {Array_A, Array_B, Array_C};
What is the correct type of ??? that I should use? I tried uint** and uint* but neither works.
If it's not doable, suppose I am not allowed to change the definition of Array_A, Array_B, ... What is a good way to define Full_Array?
Array_A, Array_B, and Array_C are all arrays of arrays of 2 ints, so they can all undergo the array-to-pointer conversion at the top level into pointer to array of 2 ints.
So Full_Array needs to be an array of pointers to arrays of 2 ints. The declaration can be written:
int (*FullArray[])[2] = {Array_A, Array_B, Array_C};
Note that there is no way to tell what the lengths of the subarrays are, unless you have sentinel values.
If the arrays Array_A, Array_B, and Array_C are of the same size, you can create pointers to them using the & operator and store them in an array. If they are of different sizes, the & operator will create different pointer types and you won't be able to store them in the pointer array.
int Array_A[3][2] = { ... };
int Array_B[3][2] = { ... };
int Array_C[3][2] = { ... };
typedef int (*PtrType)[3][2];
PtrType Full_Array[] = {&Array_A, &Array_B, &Array_C};
The following will be an error.
int Array_A[][2] = { {}, {}, {} }; // Implied dimensions [3][2]
int Array_B[][2] = { {}, {} }; // Implied dimensions [2][2]
int Array_C[][2] = { {}, {}, {} }; // Implied dimensions [3][2]
typedef int (*PtrType)[3][2];
PtrType Full_Array[] = {&Array_A, &Array_B, &Array_C};
In addition to the already posted answers, you might want to consider using decltype to automatically deduce the type:
using PtrToArrayElem =
decltype(&(Array_A[0])); // C++11, or
// std::decay_t<decltype(Array_A)>; // C++14 alternative, or
// typename std::decay<decltype(Array_A)>::type; // C++11 version of above
PtrToArrayElem arrayOfPtrsToFirstElements[] = {Array_A, Array_B, Array_C};
The benefit is that if you ever change the type of one of the arrays, then you don't need to change the code here. Just make sure to keep the rest of the code (accessing the array of pointers) generic, too.
Of course this also works if you rather want to store addresses to the arrays themselves, which will only work if they're of the same size:
using PtrToArray = decltype(&Array_A);
PtrToArray arrayOfPtrToArray[] = {&Array_A, &Array_B, &Array_C};
Note: Variable names are chosen for descriptive purposes of this answer. You should of course use meaningful names.
In my platformer game which I'm writing in Visual C++, each level will initially be stored as a 2-dimensional array of ints. I decided it would make more sense to store this array in a class, so I created a class called Level. It looks like this:
class Level {
private:
int map[20][30];
public:
Level(int a[20][30]) {
map = a;
}
int getcell(int row, int column) {
return map[row][column];
}
};
As far as I can see - from looking up tutorials on class constructors, and passing 2-dimensional arrays as parameters, this should work, so I really don't understand why it doesn't.
On the line where I do map = a, I get an error: Error: expression must be a modifiable lvalue. I've looked this error up on stackoverflow, but I can't find any answers which relate to my problem.
So, how can I fix this error?
This doesn't really have anything to do with a constructor. You cannot assign arrays in C++. Whether in the constructor, or anywhere else.
There are two ways to work around it. The first way is the brute force way. Instead of
map = a;
write a loop to copy the contents of the array from the constructor's parameter into the class member array.
The second way is to stuff the array into an intermediate class:
class Level {
public:
struct level_map {
int map[20][30];
};
private:
level_map map;
public:
Level(const level_map &initial_map) : map(initial_map)
{
}
int getcell(int row, int column) {
return level_map.map[row][column];
}
};
This may or may not be practical, and introduces a little bit more complexity.
But the real answer here is to use std::vectors instead of plain arrays, which will solve all of these problems.
Others have already mentioned the real reason: you cannot assign an array to another using = operator. My two cents about your class:
map is not a good name, it may get conflict with std::map if using namespace std; or using std::map was specified somewhere.
The constant array sizes make this class non-reusable. Class should be flexible to allow any N*M sized 2D array. For this, better to use vector<vector<int>>.
getcell should be a const method, and it should do error checking with row and column numbers passed.
If you want this class to have static-sized array sizes and compile time, you may use class templates with row and column sizes as non type template arguments.
template<size_t row, size_t column>
class Level
{
int _map[row][column];
public:
Level(int src[row][column])
{
memcpy(_map, src, sizeof(_map)); // why not simply 'memcpy' ?
}
};
int main()
{
int source[10][2] = { {1, 2}, {3,4} };
Level<10, 2> ten_by_2(source);
}
Here the map is a constant value, which could not been assigned as an lvalue. This could be fixed by iterating the element of the array, and assign a[i][j] to map[i][j].
class Level {
private:
int map[20][30];
public:
Level(int a[20][30]) {
for(int i = 0; i < 20; ++i)
for(int j = 0; j < 30; ++j)
map[i][j] = a[i][j];
}
int getcell(int row, int column) {
return map[row][column];
}
};
I have an array of vectors in one class:
class MeasurementData
{
private:
std::vector<double> m_measuredStrengths[3];
}
And I would like a function of another class to examine that and pass back an integer based on the analysis, e.g.
int CStrengthAnalyser::GetBestFit(std::vector<double> measuredStrengths[3])
{
int bestFit = -1;
// do stuff
return bestFit;
}
And I'm a little confused by the best practice for passing this kind of object around, plus setting up my receiving function to guarantee no changes to the original data.
Is my function declaration OK as-is, or do I need to add some best practice tweaks?
The function you have right now is the same function as:
int CStrengthAnalyser::GetBestFit(std::vector<double> * measuredStrengths )
So it can definitely modify the vectors. If you're always dealing with an array of size 3 you can take a const reference to an array of size 3.
int CStrengthAnalyser::GetBestFit(std::vector<double> const (&measuredStrengths)[3])
Or if you want to make it more generic:
struct CStrengthAnalyser
{
// ...
template<std::size_t N>
int GetBestFit(std::vector<double> const (&measuredStrengths)[N])
{ ... }
};
In this case the member function definition must appear in the header (or, to be precise, the definition must be visible to the compiler at the callsite).
If you want to avoid the ugly reference to array syntax you could change the MeasurementData definition to contain a std::array<std::vector<double>, 3> instead of a plain C array. Then passing a reference to that is cleaner
int CStrengthAnalyser::GetBestFit(std::array<std::vector<double>, 3> const& measuredStrengths)
And finally, you could also deduce the size of the std::array using a function template as shown previously.
I would suggest that you use a vector of vectors here, like
vector<vector<double> > your_measure(3);
When you pass it into another function, you can use the key word const to it, like
my_fun(vector<vector<double> > const & your_vec_vec);