0

I'm writting Matrix class and got to the point where I need to create an array of Array objects, but Array can't have constructor with no arguments ( it need m argument to allocate memory for it ). I searched and haven't found the solution, people only sugest doing it with Vector object, but I am not allowed to do it with anything other than arrays. Then a friend sent me the constructor for matrix that works for them, but even they don't know why it works.

Matrix::Matrix(int n, int m):n(n),m(m) {
    srand(time(0));
    this->data=new Array(n);
    for(int i=0; i<n; i++){
        this->data[i].m=this->m;
        this->data[i].data=new int[m];
        for(int j=0; j<this->m; j++){
            this->data[i].data[j]= rand()%10; 
        }
    }
}

I don't get how this this->data[i] is defined? [] operator isn't overloaded anywhere and data is only a single Array object not an array of Array-s. So why and how is this working and not an compile error?

Source files:

Header:

#define ROK04_ROK04_H

class Array{
protected:
    int* data;
    int m;

public:
    Array(int m);
    Array& operator = (const Array& a);
    virtual ~Array();
    Array& operator+=(const Array& a);
    virtual void setElem(int pos, int value);
    virtual void print() const;
    friend class Matrix;
};

class Matrix{
protected:
    Array* data;
    int n;
    int m;
public:
    Matrix(int n, int m);
};

#endif //ROK04_ROK04_H ```

#ifndef ROK04_ROK04_H
#define ROK04_ROK04_H

class Array{
protected:
    int* data;
    int m;

public:
    Array(int m);
    Array& operator = (const Array& a);
    virtual ~Array();
    Array& operator+=(const Array& a);
    virtual void setElem(int pos, int value);
    virtual void stampa() const;
    friend class Matrix;
};

class Matrix{
protected:
    Array* data;
    int n;
    int m;
public:
    Matrix(int n, int m);
    void stampaj();

};

#endif //ROK04_ROK04_H 

Cpp:

#include <iostream>
#include <ctime>
#include "rok04.h"
using namespace std;

Array::Array(int m):m(m),data( new int[m]() ){}

Array& Array::operator=(const Array& a) {
    cout << "Usao" << this << endl;
    for(int i = 0; i < m; i++){
        data[i] = a.data[i];
    }

    return *this;
}

Array::~Array() {
    delete[] data;
}

void Array::setElem(int pos, int value) {
    try {

        if(pos >= m){
            cout << "Usao\n";
            throw out_of_range("Index out of bounds!");
        }

        data[pos] = value;

    } catch (out_of_range& oor){
        cerr << oor.what() << endl;
    }
}

void Array::print() const {
//    cout << m;
    for (int i = 0; i < m; ++i) {
        cout << data[i] << " ";
    }
    cout << endl;
}

Array &Array::operator+=(const Array& a) {

    int* temp = new int(m+a.m);

    for(int i = 0; i < m; i++){
        temp[i] = data[i];
    }

    for (int i = m; i < m+a.m; ++i) {
        temp[i] = a.data[i-m];
    }

    delete[] data;
    data = temp;
    m = m+a.m;

    return *this;
}

Matrix::Matrix(int n, int m):n(n),m(m) {
    srand(time(0));
    this->data=new Array(n);
    for(int i=0; i<n; i++){
        this->data[i].m=this->m;
        this->data[i].data=new int[m];
        for(int j=0; j<this->m; j++){
            this->data[i].data[j]= rand()%10;
        }
    }
}
Comizard
  • 45
  • 4
  • 2
    `this->data` is not an object of class type - it's a pointer to `Array`. `this->data[i]` uses the built-in `[]` operator - it accesses `i`th element in the (plain) array of `Array` objects that `data` points to. Except that `data` only actually points to a single object, so `this->data[i]` exhibits undefined behavior whenever `i != 0`, by way of accessing an index out of bounds. – Igor Tandetnik Jan 09 '22 at 22:54
  • 3
    In this case, `this->data[i]` is performing **pointer arithmetic**, it is identical to `*(this->data + i)` – Remy Lebeau Jan 09 '22 at 22:55
  • The constructor doesn't work. `this->data=new Array(n);` looks like a typo for `this->data=new Array[n];` which would create `n` objects of type `Array`, but `this->data=new Array(n);` creates only one. `this->data=new Array[n];` doesn't work for you though, since `Array` requires an argument for construction. – user17732522 Jan 09 '22 at 22:58
  • If you are expected to use only `new` and not the standard library, then the only easy way out of this is to define a default constructor for `Array` which initializes the pointer to `nullptr`, and then you can assign the actual fully constructed `Array` objects in a loop. – user17732522 Jan 09 '22 at 23:00
  • Related: https://stackoverflow.com/questions/4622461/difference-between-pointer-index-and-pointer – user2864740 Jan 09 '22 at 23:01
  • No, the shown code definitely doesn't work. It might compile, but it will not work. Your "friend"'s belief that their code works, for some strange reason, it's incorrect. – Sam Varshavchik Jan 09 '22 at 23:22

1 Answers1

2

You have this definition: int* data. So by default, given a pointer operand, data[x] is translated into *(data + x) by the C++ compiler.

littleadv
  • 20,100
  • 2
  • 36
  • 50