Initialization not Working - c++

I am using trying to solve the Shortest Path problem in C++. For that I have created the following Graph() constructor.
Graph::Graph(int NumberOfVertices){
this->NumberOfVertices=NumberOfVertices;
cout<<"Graph()"<<endl;
//declaring the weight matrix
WeightMatrix=new int*[NumberOfVertices];
for(int a=0;a<NumberOfVertices;a++)
WeightMatrix[a]=new int[NumberOfVertices];
//initialising the weight matrix
WeightMatrix[NumberOfVertices][NumberOfVertices]={0};
ShortestPathArray=new int[NumberOfVertices];
}
I have two questions.
Why is a simple declaration like
WeightMatrix=new int[NumberOfVertices][NumberOfVertices] not allowed? I tried doing so but there were errors. I found the solution online, but am not able to understand it.
The initialization step is not working. The code doesn't proceed further than this statement WeightMatrix[NumberOfVertices][NumberOfVertices]={0};
When I comment out this step everything works fine.

Question #1:
The type of WeightMatrix is int**, so you cannot initialize it with new int[...].
As you seem to have already fixed in your code, the right way is to initialize it with new int*[...].
Question #2:
Initializing an array to a list of values is allowed only at declaration. For example:
int WeightMatrix[M][N] =
{
{1,2,3,...},
{4,5,6,...},
...
};
So you can fix the compilation error by changing this:
WeightMatrix[NumberOfVertices][NumberOfVertices]={0};
To this:
for (int i=0; i<NumberOfVertices; i++)
for (int j=0; j<NumberOfVertices; j++)
WeightMatrix[i][j] = 0;

Why is a simple declaration like WeightMatrix=new int[NumberOfVertices][NumberOfVertices] not allowed? I tried doing so but there were errors. I found the solution online, but am not able to understand it.
It should help to compare this to creation of an array on the stack, for which you can do:
int my_array[X][Y];
When you later say my_array[x][y], the compiler's record of the value Y is used to find the int value at address &my_array + x * Y + y. But, when you use new and specify a dimension at run-time, the compiler isn't obliged to store the dimension(s) involved - that would adversely affect run-time memory usage and performance. Without such dimensions though, the compiler can't support a [x][y] notation, so it's misleading to let you use new as if it were creating a multi-dimensional array. In practice, implementations sometimes store the single allowed array dimension in some extra memory they ask for when you use new[] so they can iterate over the right number of elements to call destructors, but they might want to avoid that for types such as int that require no destruction.
The expectation is that you'll work out the total number of elements you need:
int* weightMatrix = new int[NumberOfVertices * NumberOfVertices];
Then what's conceptually weightMatrix[x][y] can be stored at weightMatrix[x * NumberOfVertices + y] (or if you prefer weightMatrix[x + NumberOfVertices * y]).
I recommend writing a simple class that has an operator to provide a convenient notation ala matrix(x, y):
template <typename T>
class Matrix
{
Matrix(size_t X, size_t Y = X) : X_(X), Y_(Y), p_(new T[X * Y]) { }
~Matrix() { delete[] p_; }
T& operator()(size_t x, size_t y) { return p_[x * Y + y]; }
const T& operator()(size_t x, size_t y) const { return p_[x * Y + y]; }
size_t X_, Y_;
T* p_;
};
Then you can write simpler, cleaner and more robust client code:
Matrix matrix(20, 10);
matrix(4, 2) = 13;
You can also easily put checks in operator() to catch out-of-bound indexing during development and testing.

Related

What is the equivalent matrix-like C-array of a nested std::vector (for C and C++ interop)?

What is the equivalent matrix-like C-array of a nested std::vector (for C and C++ interop)?
For example, if one wanted to treat std::vector<std::vector<int>> as some kind of int arr[n][m], where n is the dimension of the outer vector and m of the inner vector, then what structure would one use in C?
This is motivated by wanting to have a similar correspondence between matrices in C and C++ as for vectors in:
https://stackoverflow.com/a/1733150/4959635
Based on additional information in the comments, let me suggest you do something like this instead:
class TwoDimVector {
public:
TwoDimVector(int num_cols, int num_rows)
: m_num_cols(num_cols)
, m_num_rows(num_rows)
, m_data(m_num_cols * m_num_rows, 0)
{ }
int & ix(int row, int col) {
return data[num_cols * row + col];
}
const int m_num_rows;
const int m_num_cols;
private:
std::vector<int> m_data;
}
When you do nested vectors, there's a lot of extra work happening. Also, with nested vectors, the data is not contiguous, making it hard to work with any C-apis. Notice with this data structure, the size is fixed at construction time and accessible. This is designed to be row contiguous, so for C interoperability you can access extra raw pointers like so:
TwoDimVector tdv(4,3);
int * raw = &tdv.ix(0,0);
int * raw_second_row = &tdv.ix(1,0);
Just note: if you pass this into a function, be sure to pass by reference:
void do_work(TwoDimVector & tdv) {
...
}
If you don't pass by reference, it will copy everything, which is a bunch of (typically unnecessary) work.
Maybe, this code
void translate(const vector< vector >& vec){
int m = vec.size(), n = 0;
for (vector<int>& deep : vec) // search maximum size if nested vectors
{
if (deep.size() > n)
n = deep.size();
}
int arr[m][n];
m = n = 0;
for (vector<int>& deep : vec){
for (int& x : deep)
{
arr[m][n] = x;
++n;
}
++m;
}
// So, I really don't know how you can return this array :(
}
You see, it code is BAD, you mustn't do it !!!
If you writing on C++ you should using std::vector - it is easier.
C-like arrays is heritage from C, you shouldn't using they

C++ arrow to overloaded index ( this->[ ] )

I have a simple class, whose index operator I've overloaded:
class dgrid{
double* data; // 1D Array holds 2D data in row-major format
public:
const int nx;
const int ny;
double* operator[] (const int index) {return &(data[index*nx]);}
}
This way dgrid[x][y] works as a 2d array, but the data is contiguous in memory.
However, from inside member functions this is a little more clunky, I need to do something like (*this)[x][y] which works, but seems smelly, especially when I have sections like:
(*this)[i][j] = (*this)[i+1][j]
+ (*this)[i-1][j]
+ (*this)[i][j+1]
+ (*this)[i][j-1]
- 4*(*this)[i][j];
Is there a better way to do this? Something like this->[x][y] (but this doesn't work). Is using a little function f(x,y) returns &data[index*nx+ny] the only option?
You could overload ->, but why not simply do:
T& that = *this; //or use auto as t.c. suggests
that[i][j] = that[i+1][j]
+ that[i-1][j]
+ that[i][j+1]
+ that[i][j-1]
- 4*that[i][j];
That's (pun) at least as readable as this->[][]. No ?

c++ overloading operator [] efficiency

I just wanted to know how to overload the operator [] to acces a matrix within a class, and I found how to that here.
But, I have a question about this: Which way of changing a matrix will be more efficient?
1: Overloading the operator []: (code extracted from the previous link)
class CMatrix {
public:
int rows, cols;
int **arr;
public:
int* operator[]( int const y )
{
return &arr[0][y];
}
....
Edit: I relied too much on the other example: Should it work this way?
int* operator[]( int const x )
{
return &arr[x];
}
2:Using a "normal" method:
class CMatrix {
public:
int rows, cols;
int **arr;
public:
void changematrix( int i, int j, int n)
{
arr[i][j]=n;
}
...
Edit: Fixed const on changematrix
Write correct, readable code and let the compiler worry about efficiency.
If you have performance problems, and if when you run a profiler to measure the performance (which you MUST do before trying to optimize) this code shows up as a performance issue, then you can:
1) Examine the assembly language interpretation of the code generated by the compiler with full optimization enabled, or
2) Try it both ways, measure, and pick the faster one.
The results will be highly dependent on the compiler you are using and the flags you specify for that compiler.
Neither method will work as you have declared
int **arr;
gives no row length information for:
return &arr[0][y];
arr[i][j]=n;
I would go for a third option, using operator() instead of operator[]:
int& operator()(size_t i, size_t j) {
return arr[i][j];
}
int operator()(size_t i, size_t j) const {
return arr[i][j];
}
The user will then do:
CMatrix m = ...
m(1,2) = 5;
std::cout << m(1,2);
Other than that, I would really consider whether the way of laying out the data internally the the most efficient. Is this a jagged array? Or do all rows have the same width? If this represents a rectangle shaped array (i.e. all rows have the same number of columns) you might be better off storing all elements in a single 1D array, and using some basic arithmetic to locate the correct element.

2D array as instance variable of class

So if I have a class with a 2D array that I want to initialize with two parameters passed into the constructor, how would I do that, I keep running into errors because it won't let me update the two-d array at all in the constructor.
-- Update from the comments:
In my header file I tried both
int array[][]
and
int **array
and then in the .cpp file in the constructor I'm trying to do
array = new int[arg1][arg2]
Neither declaration of the array in the header file worked.
in the constructor I'm trying to do array = new array[arg1][arg2]
You need to specify the array type, like
array = new int[arg1][arg2];
Note that this works in C++11 only - when using older standards, the second array size needs to be const (which is probably not what you want).
There are also some additional articles discussing the same issue:
Multi-Dimensional Arrays
How to "new" a two-dimension array in C++?
Ideally, since you are using C++ anyway, you should use std::vector as proposed in another answer.
Vectors use a lot of overhead though, don't they? I'm trying to keep my memory use light. –
Start with std::vector. Once your application is running properly from a functional perspective, if you are still concerned about memory usage and/or performance, do benchmarking. If you properly encapsulate your 2D array in a class, you can always change the actual implementation of the array with no impact on the code which uses it.
Technically, if you want to make sure that you have one flat memory area which contains your array, you could use a 1-dimensional array to simulate a 2-dimensional array, like in the following code (just to get you the idea, certainly needs some improvement, especially copy construction and assignment operators are missing):
class Array2D {
private:
int *array;
int size1;
public:
Array2D(int arg1, int arg2) {
size1 = arg1;
array = new int[arg1 * arg2];
}
~Array2D() {
delete[] array;
}
int& at(int i1, int i2) {
return array[i1 * size1 + i2];
}
};
int main() {
Array2D array(10, 10);
array.at(2, 2) = 42;
std::cerr << array.at(2, 2);
return 0;
}
Simplest solution would be:
std::vector<std::vector<VALUE>> arr2(X, std::vector<VALUE>(Y));
Here is an 2d array example with bounds check and custom type, based upon the example from Andreas Fester.
#include <stdexcept>
template <typename T>
class Array2D {
private:
T *array;
unsigned int sizeX;
unsigned int sizeY;
public:
Array2D(unsigned int X, unsigned int Y) {
sizeX = X;
sizeY = Y;
array = new T[X * Y];
}
~Array2D() {
delete[] array;
}
T& at(unsigned int X, unsigned int Y) {
if((X > sizeX) || (Y > sizeY))
throw std::out_of_range("Bla bla");
return array[X * sizeX + Y];
}
};
int main() {
double MyValue;
Array2D<double> *MyArray = new Array2D<double>(10, 100);
MyArray->at(1,1) = 10.1;
MyValue = MyArray->at(1,1);
printf("Array value = %3.3f\n", MyValue);
return 0;
}

C++ Matrix Class with Operator Overloading

I was implementing a small dense matrix class and instead of plan get/set operators I wanted to use operator overloading to make the API more usable and coherent.
What I want to achieve is pretty simple:
template<typename T>
class Matrix
{
public:
/* ... Leaving out CTOR and Memory Management for Simplicity */
T operator() (unsigned x, unsigned y){/* ... */ }
};
Matrix<int> m(10,10);
int value = m(5,3); // get the value at index 5,3
m(5,3) = 99; // set the value at index 5,3
While getting the value is straight forward by overloading operator(), I can't get my head around defining the setter. From what I understood the operator precedence would call operator() before the assignment, however it is not possible to overload operator() to return a correct lvalue.
What is the best approach to solve this problem?
I dispute that "it's not possible" to do the correct thing:
struct Matrix
{
int & operator()(size_t i, size_t j) { return data[i * Cols + j]; }
const int & operator()(size_t i, size_t j) const { return data[i * Cols + j]; }
/* ... */
private:
const size_t Rows, Cols;
int data[Rows * Cols]; // not real code!
};
Now you can say, m(2,3) = m(3,2) = -1; etc.
The answer to your question is what Kerrek already stated: you can provide an overload by changing the signature of the operator, which in this case can be achieved by modifying the const-ness of the function.
But I would recommend that you at least consider providing a separate setter for the values. The reason is that once you return references to your internal data structures you loose control of what external code does with your data. It might be ok in this case, but consider that if you decided to add range validation to the implementation (i.e. verify that no value in the matrix is above X or below Y), or wished to optimize some calculation on the matrix (say the sum of all of the elements in the matrix is an often checked value, and you want to optimize away the calculation by pre-caching the value and updating it on each field change) it is much easier to control with a method that receives the value to set.