double tab[] VS vector<double> tab

Hi!

I have a question (surprise huh?).
The code below works just fine, however i wonder if there is any way to replace:
double arr[64];

with:
vector<double> arr[64];

...and to have the operator overloading still working - when I use a vector there is a problem with returning "arr".

Help plz :)



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
using namespace std;

struct mat
{
    double arr[64];// for example
    int cols;// length of each row

    double* operator[](int r){ return arr + r*cols; }// overload []

    // ctor provides easy initialization for this example
    mat(int Cols): cols(Cols)
    {
        for(int i=0; i<64; ++i)
            arr[i] = i;
    }
};

int main()
{
    mat m(8);// sets m up with 8 doubles per row
    cout << m[4][3] << endl;// outputs 35 = 4*8+3 - works as rvalue
    m[5][2] = 8.5;// test for use as an lvalue
    cout << m[5][2] << endl;// gives 8.5 so lvalue test is good.
    return 0;
}
certainly:

1
2
3
4
5
6
7
8
9
10
11
12
13
struct mat
{
    vector<double> arr;
    int cols;

    double* operator[](int r){ return &arr[r*cols]; }

    mat(int Cols) : arr(64 * Cols), cols(Cols)
    {
        for(int i=0; i<64; ++i)
            arr[i] = i;
    }
};
@Cubbi - the 64 * Cols doesn't look quite right?

Anyway...

If you're going to the trouble of writing an ADT for your matrix, I'd consider going a bit further and, rather than return a double*, use a helper class so you can control access to the elements.

The nested row class is a kind of range-checking replacement for the double* pointer.

out_of_range is the same exception throw by vector::at() when you try to use an invalid index. if throwing an exception seems a bit heavy handed, it could be replaced with an assertion in the debug build.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include <vector>
using namespace std;

class mat {
private:
    vector<double> arr;
    int rows;
    int cols;

public:
    class row {
    private:
        int     cols;
        double* prow;

        // can only be constructed by parent matrix
        row(int Cols, double* pRow)
        : cols(Cols), prow(pRow) {
        }

    public:
        double& operator[](int c) {
            if((0 > c) || (c >= cols))
                throw out_of_range("invalid column");
            return prow[c];
        }

    friend class ::mat;
    };

    row operator[](int r) {
        if((0 > r) || (r >= rows))
            throw out_of_range("invalid row");
        return row(cols, &arr[r*cols]);
    }

    mat(int Rows, int Cols)
    : arr(Rows * Cols), rows(Rows), cols(Cols)
    {
        for(int i=0; i<(rows * cols); ++i)
            arr[i] = i;
    }
};

int main() {
    try {
        mat m(8, 8);// sets m up with 8 doubles per row
        cout << m[4][3] << endl;// outputs 35 = 4*8+3 - works as rvalue
        m[5][2] = 8.5;// test for use as an lvalue
        cout << m[5][2] << endl;// gives 8.5 so lvalue test is good.
        m[7][7] = 3;
        cout << m[7][7] << endl;
        m[7][7] = m[7][7] * m[7][7];
        cout << m[7][7] << endl;
        m[13][13] = 666.0;
    }
    catch(const out_of_range& e) {
        cerr << "error : " << e.what() << endl;
    }

    return 0;
}


Andy
Last edited on
Topic archived. No new replies allowed.