0

I'm new to C++ and the way 2D arrays work is confusing me. I've been reading online and trying to understand what's causing my specific issue, but have come up with nothing.


According to this Stack Overflow answer, I should be able to get a value in my 2D array by doing this: (*myArrayObject)[row][col], but it throws the following error:

error: invalid types 'int[unsigned int]' for array subscript  
  return (*myArrayObject)[row][col];  
                                  ^  

And if I try to do myArrayObject[row][col] it throws the following error:

error: invalid initialization of non-const reference of types 'double&' from an rvalue of type 'double'  
  return myArrayObject[row][col];
                               ^  

Here's the full (related/concise) code in question:

main.cpp

#include "matrix.h"

using namespace std;

typedef unsigned int uint;

int main() {

 Matrix * matrix; //This could be the problem, but not sure what else to do
 matrix = new Matrix(10, 1);

 for(uint i = 0; i < matrix->numRows(); ++i) {
   for(uint j = 0; j < matrix->numCols(); ++j) {
     cout << matrix->at(i,j) << " " << endl;
   }
 }  
 return 0;
}

matrix.h

typedef unsigned int uint;  

class Matrix {  
public:
    Matrix(uint rows, uint cols); //Constructor
    const uint numRows() const;                  
    const uint numCols() const;                  

    void setRows(const uint &);                  
    void setCols(const uint &);                 

    double & at(uint row, uint col);
private:
    uint rows, cols;
    int ** matrix; //This could also be the problem, but not sure what else to do

    void makeArray() {
      matrix = new int * [rows];
      for(uint i = 0; i < rows; ++i) {
        matrix[i] = new int [cols];
      }
    }  
};

matrix.cpp

#include "matrix.h"

typedef unsigned int uint;

Matrix::Matrix(uint rows, uint cols) {
  //Make matrix of desired size
  this->setRows(rows);
  this->setCols(cols);

  //Initialize all elements to 0
  for(uint i = 0; i < rows; ++i) {
    for(uint j = 0; j < cols; ++j) {
      this->matrix[i][j] = 0;
    }
  }
}

const uint Matrix::numRows() const {
  return this->rows;
}

const uint Matrix::numCols() const {
  return this->cols;
}

void Matrix::setRows(const uint & rows) {
  this->rows = rows;
}

void Matrix::setCols(const uint & cols) {
  this->cols = cols;
}

double & Matrix::at(uint row, uint col) {
  return matrix[row][col]; //NOT WORKING
}

SOLUTION:
Changes made to matrix.h:

double ** matrix;

void makeArray() {
  matrix = new double * [rows];
  for(uint i = 0; i < rows; ++i) {
    matrix[i] = new double [cols];
  }
}  

Changes made to matrix.cpp:
added makeArray() to constructor.

Community
  • 1
  • 1
Mazzone
  • 318
  • 1
  • 4
  • 20
  • 1
    `myArrayObject[row][col]` would seem to be what's for dinner, though frankly I'd be using a single-dimension `std::vector` and doing the row/column math in the `at` member to get the correct element. And btw, you're going to have a hard time returning `double &` from a matrix declared as `int`. – WhozCraig Jul 09 '16 at 04:08

2 Answers2

3
  1. As WhozCraig and Rakete1111 said, your problem is, you can't return a reference to double, when your data is all int.

But you may have other problems even after fixing that.

  1. You never call your makeArray function and/or in your constructor you never allocate (new) your array, like you did in makeArray.

Not a problem yet, but.

  1. You don't need any setters for rows and cols values. Or, you need to change these setters in such a way, that a new matrix is reallocated to fit the new sizes.

  2. #include is the same thing, as copy & pasting the contents of the named file. And you have a typedef for uint which simply get copy pasted from matrix.h to matrix.cpp and main.cpp, so it would work even, if you don't specify it again.

  3. You have a using namespace std, but no std headers included. You may need that thing, e.g. if you #include <iostream> or <vector> or any other standard library header. Or if for some reason you wrote code in your own namespace std {...} block.

iwat0qs
  • 146
  • 3
  • 10
  • The code I've currently got in my main.cpp is solely for testing purposes - I just wanted to see if the array was actually storing anything, and it is! Also, with your third point, is that going to be an issue considering that my program isn't going to be asking for any user input? It's all going to be directly typed into main.cpp and executed. So if a new array needs to be made, they'll initialize and fill a new one. – Mazzone Jul 09 '16 at 04:38
  • @Mazzone If so, you still need no setters, because you won't be using them this way :) – iwat0qs Jul 09 '16 at 12:10
1

matrix[row][col] is the right way to do it, as matrix is an int**, and applying operator[] two times is like deferencing the pointer two times, and you'll get an individual int.

The reason though why you get an error because at returns a double&. Let me explain, matrix[row][col] returns an int, and this int gets promoted to a double. That double is a temporary variable, and you can't make a reference out of a temporary variable, and that's why the compiler complains.

Making at return an int& would obviously solve it :)

Rakete1111
  • 47,013
  • 16
  • 123
  • 162
  • After changing occurrences of `int` to `double` in my header file, it compiles okay, but it still doesn't work. Now it's just giving me a segmentation fault (core dumped) error. – Mazzone Jul 09 '16 at 04:24
  • 1
    @Mazzone you are not calling `makeArray` :) – Rakete1111 Jul 09 '16 at 04:29
  • Ah... I took it out of my matrix.cpp file when I was trying another method earlier. Thank you! A more familiar mind is always helpful. – Mazzone Jul 09 '16 at 04:32