Klasa macierz - przypisanie wyniku operacji +/-/*

0

Witam piszę sobie mały programik, ale jedna rzecz mi nie daje spokoju.
Na początku tworzę sobie przykładowe dwie macierze (macierz1, macierz2) np. takie:
|1 2 3|
|4 5 6|
|7 8 9|
Potem tworzę sobie macierz3 (która na początku wygląda jak powyżej).
Następnie do tej macierz3 przypisuję wynik np dodawania tych macierz1 + macierz2. Wtedy jak wypisuję macierz3 na ekran to w pierwszych dwóch wyrazach pierwszego wiersza pojawia mi się jakiś syf/śmiecie (np. 8524067, 8521234). W pozostałych wyrazach jest wszystko w porządku. Rozmiar macierzy nie ma znaczenia. Czy to macierz 2x2, 3x3, 5x5 to dwa pierwsze wyrazy zawsze są złe. Przy każdej operacji +/-/* jest to samo.
Dodam, że jak wykonuję pojedyncze instrukcje typu:
cout << macierz1 + macierz2;
lub
macierz3 = macierz1;
cout << macierz3;
to wszystko jest w porządku.
Problem się pojawia tylko w przypadku typu:
macierz3 = macierz1 + macierz2;
cout << macierz3;

 
#include <iostream>
using namespace std;

class macierz {
    int rozmiar; //rozmiar macierzy
    int *wskaznikNaMacierz; //wskaznik na macierz
public:
    friend istream& operator >> (istream&, macierz&);
    friend ostream& operator << (ostream&, const macierz&);
    friend macierz operator + (const macierz&, const macierz&);
    friend macierz operator - (const macierz&, const macierz&);
    friend macierz operator * (const macierz&, const macierz&);
    macierz(int);
    macierz(const macierz&);
    ~macierz();
    macierz macierzTransponowana(const macierz&);
    macierz macierzOdwrotna(const macierz&);
    double wyznacznik();
};

macierz::macierz(int n){
    rozmiar = n;
    wskaznikNaMacierz = new int[rozmiar * rozmiar];
    for(int i = 0; i < rozmiar; ++i)
        for(int j = 0; j < rozmiar; ++j)
            *(wskaznikNaMacierz + i * rozmiar + j) = i+j+1; // domyslnie będzie  = 0, ale tak nie trzeba za każdym razem wprowadzać danych z palca
}

macierz::macierz(const macierz &m) {
    rozmiar = m.rozmiar;
    wskaznikNaMacierz = new int[rozmiar * rozmiar];
    for (int i = 0; i < rozmiar; ++i)
        for (int j = 0; j < rozmiar; ++j)
            *(wskaznikNaMacierz + i * rozmiar + j) = *(m.wskaznikNaMacierz + i * rozmiar + j);
}

macierz::~macierz() {
    delete wskaznikNaMacierz;
}

istream& operator >> (istream& wejscie, macierz& m) {
    cout << "Podaj rozmiar macierzy: ";
    wejscie >> m.rozmiar;
    cout << "Podaj wyrazy macierzy wierszami:\n";
    for(int i = 0; i < m.rozmiar; ++i)
        for(int j = 0; j < m.rozmiar; ++j)
            wejscie >> *(m.wskaznikNaMacierz + i * m.rozmiar + j);
    return wejscie;
}

ostream& operator << (ostream& wyjscie, const macierz& m) {
    cout << "Wygenerowano macierz:\n";
    for(int i = 0; i < m.rozmiar; ++i) {
        for(int j = 0; j < m.rozmiar; ++j)
            cout << *(m.wskaznikNaMacierz + i * m.rozmiar + j) <<"\t";
        cout << endl;
    }
    return wyjscie;
}

macierz operator + (const macierz& m1, const macierz& m2) {
    macierz wynik(m1.rozmiar);
    for(int i = 0; i < m1.rozmiar; ++i)
        for(int j = 0; j < m1.rozmiar; ++j)
            *(wynik.wskaznikNaMacierz + i * m1.rozmiar + j) = *(m1.wskaznikNaMacierz + i * m1.rozmiar + j) + *(m2.wskaznikNaMacierz + i * m1.rozmiar + j);
    return wynik;
}

macierz operator - (const macierz& m1, const macierz& m2) {
    macierz wynik(m1.rozmiar);
    for(int i = 0; i < m1.rozmiar; ++i)
        for(int j = 0; j < m1.rozmiar; ++j)
            *(wynik.wskaznikNaMacierz + i * m1.rozmiar + j) = *(m1.wskaznikNaMacierz + i * m1.rozmiar + j) - *(m2.wskaznikNaMacierz + i * m1.rozmiar + j);
    return wynik;
}

macierz operator * (const macierz& m1, const macierz& m2) {
    macierz wynik(m1.rozmiar);
    int tmp;
    for(int i = 0; i < m1.rozmiar; ++i)
        for(int j = 0; j < m1.rozmiar; ++j) {
            tmp = 0;
            for(int k = 0; k < m1.rozmiar; ++k)
                tmp += *(m1.wskaznikNaMacierz + i * m1.rozmiar + k) * *(m2.wskaznikNaMacierz + k * m1.rozmiar + j);
            *(wynik.wskaznikNaMacierz + i * m1.rozmiar + j) = tmp;
        }
    return wynik;
}


int main(int argc, char *argv[]) {
    macierz macierz1(3);
    macierz macierz2(3);
    macierz macierz3(3);

    cout << macierz1 << endl;
    cout << macierz2 << endl;
    macierz3 = macierz1 + macierz2;


    cout << "Suma macierzy:\n" << macierz3 << endl;
    //cout << "Iloczyn macierzy:\n" << macierz3 << endl;



    //cout << "Nowa macierz:\n";
    //cin >> macierz3;
    //cout << macierz3 << endl;

    return 0;
}

Jakieś pomysły/rady ???

0

Po pierwsze primo, musisz zaimplementował własny operator= (i jeszcze operator==, operator!= ale nie w tym błąd) dlatego, że ten domyślny (wygenerowany przez kompilator) przepisze wszystko na pałe - razem ze wskaźnikiem, a nie wartością pod tym wskaźnikiem. Po operacji
macierz3 = macierz2 masz nagle macierz3.wskaznikNaMacierz == macierz2.wskaznikNaMacierz. To poważny błąd, bardzo poważny. Chociażby dlatego, że masz wyciek pamięci + UB (dwa razy w destruktorze zwalniasz pamięc pod obiektem).
Po drugie primo dlaczego tak brzydko używasz tych wskaźników. Nie po to jest operator[], żeby się tak bawić w to.

W ogóle Twoje operatory nie trzymają się najnowszych standardów, nie powinno być to tak napisane.

0

Dzięki za wskazówki.
Pomyślę nad rozwiązaniem i tym operatorem [].

1 użytkowników online, w tym zalogowanych: 0, gości: 1