1

I am trying to make functions(adding, subtracting, product, etc) taking as arguments dynamic 2-d arrays.

For example, given two 2-d double arrays with each one having 2 rows and 2 columns:

double** m1;

m1 = new double *[2];

for (int i = 0; i < 2; ++i) {
    m1[i] = new double[2];
}

double k1 = 1.0;
for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 2; ++j) {
        m1[i][j] = k1;
        k1 += 2.0;
    }
}

double** m2;

m2 = new double *[2];
for (int i = 0; i < 2; ++i) {
    m2[i] = new double [2];
}

double k2 = 2.0;
for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 2; ++j) {
        m2[i][j] = k2;
        k2 += 2.0;
    }
}

And I made an adding function for them. It first checks whether the two arrays have the same numbers of rows and columns. But as the arrays are totally dynamic(both numbers of rows and columns) and were declared as pointers to pointers, I can't get the numbers of rows and columns.

For example, The value of

sizeof(m1[0]) 

is 4, that is, the bite size of double pointer (probably) but, the value of

sizeof(m1[0][0]) 

is 8 which is the right size of double type.

I want the adequate version of the former.

double** add_m(double **m1_, double** m2_) {
//HERE first part that needs the numbers of arguments' rows and columns.
    if ((sizeof(*m1_) != sizeof(*m2_)) || (sizeof(**m1_) != sizeof(**m2_))) {
        cout << "The sizes of the matrices don't match each other";
        return 0;
    }
    else {
//HERE second part that needs the numbers of arguments' rows and columns.
        int num_rows = sizeof(m1_[0])/sizeof(m1[0][0]);//??
        int num_cols = sizeof(m1_[0][0])/sizeof(m1_[0][0]);//??
        double** res;
        res = new double*[num_rows];
        for (int i = 0; i < num_rows; ++i) {
            res[i] = new double[num_cols];
        }

        for (int i = 0; i < num_rows; ++i) {
            for (int j = 0; j < num_cols; ++j) {
                res[i][j] = m1_[i][j] + m2_[i][j];
            }
        }
        return res;
    }
}

EDIT: Most of answers say using already existing tools like vector, matrix. Then only for curiosity, no way of doing it? The only way is making vector-like class or matrix-like class from scratch?

Philip8
  • 67
  • 1
  • 5
  • 1
    you can use `std::array` and its `size()` – pergy Jul 26 '17 at 06:19
  • 4
    I would suggest a `class Matrix` which stores number of rows, number of columns, and a vector<> for values. Two dim-access can be achieved by resp. methods or even operator overloading. – Scheff's Cat Jul 26 '17 at 06:20
  • 1
    Also worth looking at is `std::vector` as you never properly de-allocate any of these things so this code leaks memory like crazy. – tadman Jul 26 '17 at 06:20
  • Thinking twice, you need to store number of rows, and the vector<>. Number of columns can be determined on the fly by vector<>::size() / nRows. – Scheff's Cat Jul 26 '17 at 06:21
  • @pergy Yes it is a good way. But isn't there any method to access directly them? I am curious. – Philip8 Jul 26 '17 at 06:22
  • 2
    If you pass C arrays as function arguments, they "decay" to pointers. Thus, `sizeof` cannot provide the size of array inside the function. – Scheff's Cat Jul 26 '17 at 06:23
  • @tadman yes I need to delete them. thanks – Philip8 Jul 26 '17 at 06:25
  • A similar question: [SO: Passing a 2D array to a C++ function](https://stackoverflow.com/q/8767166/7478597) – Scheff's Cat Jul 26 '17 at 06:25
  • Other similar questions: [SO: 2D arrays with C++](https://stackoverflow.com/q/1285457/7478597), [SO: How do I declare a 2d array in C++ using new?](https://stackoverflow.com/q/936687/7478597) – Scheff's Cat Jul 26 '17 at 06:29
  • Please, note, `sizeof m1[0]` (as well as `sizeof m1[0][0]`) simply evaluates the types of these expressions. It is solved at compile time. It doesn't consider what you do with `m1` at run-time (especially not if you use type-casting in a "creative" way). – Scheff's Cat Jul 26 '17 at 06:35
  • @Scheff Wow the comment looks useful and a little bit difficult. Thanks! – Philip8 Jul 26 '17 at 06:46
  • "the comment looks useful and a little bit difficult." Yeah. After decades of using C++ in professional work, I must admit, I still consider C++ "a little bit difficult"... – Scheff's Cat Jul 26 '17 at 06:55

2 Answers2

1

It seems that what you want to do is to handle matrices.

Unfortunatelly, dynamic memory allocation doesn't store the size of the allocated memory.

These are some alternatives:

Store the matrix dimensions by yourself

Then you would need to pass the matrix dimensions as a parameter to your functions. For your example, you could do something like this:

double** add_m(double **m1_, double** m2_, unsigned width, unsigned height)

Use std::array or std::vector

These classes store the number of elements.

#include <array>
#include <vector>
using namespace std;
// ...
array<array<double, 3>, 3> m1 = {{ {1, 0, 0}, {0, 1, 0}, {0, 0, 1} }};
unsigned height = m1.size();
unsigned width = m1[0].size();
vector<vector<double> > m2 = {{ {0, 1, 0}, {1, 0, 0}, {0, 0, 1} }};
height = m2.size();
width = m2[0].size();

Make your own Matrix class

That keeps track of the number of elements and encapsulates the operations that can be done with them.

Use an external library which defines a "Matrix" class

If you make a quick google search you will find a tone (keywords: linear algebra library).

These are some I tested and liked:

tuket
  • 2,117
  • 1
  • 19
  • 33
1

Size of() operator in C/C++ will give you the size of the data type passed in. So in your example when you say sizeoff(m1_) you will get the size of double pointer but not the size of memory behind it. As far as I know there is no clean way of doing what you want to do.

A better way of doing this as @Scheff suggested in comments is having a wrapper class for your matrix and storing your matrix in a std::vector (either row or column wise) and pass this class to your functions to do arthematics.

This approach has advantage of having no memory leaks and also memory continuity (for performance).

And if you are not restricted to use external libraries ... Libraries like Eigen can make it easy for you.

AdityaG
  • 406
  • 3
  • 13