Разница между инициализацией объекта и назначением объекта - PullRequest
0 голосов
/ 31 марта 2020

Я работаю над некоторой базовой c практикой объектов и столкнулся с этой проблемой.

Этот класс называется Matrix, и я попытался инициализировать a7 в a2.mutiply(a5).

Но результат сильно отличается, когда я сначала попытался инициализировать a7, а потом присвоить a2.mutiply(a5).

Я думал, что эти два кода совпадают, но результат сказал, что я неправильно.

Может ли кто-нибудь помочь мне указать на проблему?

Matrix.h

// This is part of Martax.h codes.

class Matrix {
private:
    double ** data;     
    int row;            
    int col;
public:
    Matrix();  
    Matrix(int, int);  
    Matrix(int, int, double[], int);
    Matrix(const Matrix &); 

    ~Matrix();

    Matrix add(const Matrix &); 
    Matrix multiply(const Matrix &);    
    Matrix transpose();
    void displayData();
};

Matrix::Matrix()
{
    row = 2;
    col = 2;

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

Matrix::Matrix(int a ,int b)
{
    row = a;
    col = b;
    data = new double*[row];
    for (int i = 0; i < row; i++)
        data[i] = new double[col]{0};
}

Matrix::Matrix(int a, int b, double c[], int d) 
{
    row = a;
    col = b;
    data = new double*[row];
    int w = 0;
    for (int i = 0; i < row; i++)
        data[i] = new double[col]{0};

    for (int i = 0; i < row; i++) 
        for (int j = 0; j < col; j++)
        {
            if (w<d)
                data[i][j] = c[w];

            w++;
        }
}

Matrix::Matrix(const Matrix &a)
{
    row = a.row;
    col = a.col;
    data = new double*[row];
    for (int i = 0; i < row; i++)
        data[i] = new double[col];

    for (int i = 0; i < row; i++)
        for (int j = 0; j < col; j++)
            data[i][j] = a.data[i][j];
}

Matrix::~Matrix()
{
    for (int i = 0; i < row; i++)
        delete[] data[i];

    delete[] data;
}

Matrix Matrix::add(const Matrix &a)
{
    static Matrix a5(row,col);
    for (int i = 0; i < row; i++)
        for (int j = 0; j < col; j++)
            a5.data[i][j]=data[i][j] + a.data[i][j];

    return  a5;
}
Matrix Matrix::multiply(const Matrix &a)
{
    double *z;
    z = new double[row*a.col]{0};
    int w = 0;
    int u = 0;
    for (int i = 0; i<row; i++) 
    {
        while (a.col>u)
        {
            for (int j = 0; j < col; j++)
                z[w]+=(data[i][j])*(a.data[j][u]);  

            w++;
            u++;
        }
        u = 0;
    }

    return  Matrix(row,a.col, z, row*a.col);          
}
Matrix Matrix::transpose()
{
    double *z;
    z = new double[row*col];
    int w = 0;
    for (int j = 0; j< col; j++)
        for (int i = 0 ; i < row; i++)
        {
            z[w] = data[i][j];
            w++;
        }

    return  Matrix(col,row,z,row*col);
}
void Matrix::displayData() 
{
    for (int i = 0; i < row; i++) 
    {
        for (int j = 0; j < col; j++) 
           cout << setw(3) << data[i][j];
        cout  << endl;
    }
}

Источник. cpp

#include<iostream>
#include "Matrix.h"
using namespace std;
int main()
{
    double c[4] = { 1,2,3,4 };
    Matrix a2(2, 2, c, 4);

    Matrix a5(2, 4, d, 8);

    Matrix a7 = a2.multiply(a5);


    cout << "a2 -->";
    a2.displayData();

    cout << "a5 -->";
    a5.displayData();

    cout << "a7 -->";
    a7.displayData();

    a7 = a2.multiply(a5);
    cout << "a7 -->";
    a7.displayData();

    system("pause");
    return 0;
}

Result.txt

"Source.cpp.exe"
Process started (PID=12908) >>>
a2 -->row = 2, column = 2
  1  2
  3  4
a5 -->row = 2, column = 4
  1  2  1  2
  1  2  1  2
a7 -->row = 2, column = 4
  3  6  3  6
  7 14  7 14
a7 -->row = 2, column = 4
<<< Process finished (PID=12908). (Exit code -1073741819)
================ READY ================

1 Ответ

0 голосов
/ 31 марта 2020

Программа имеет неопределенное поведение, поскольку вы не определили явно оператор копирования (или перемещения).

После этого оператора

a7 = a2.multiply(a5);

временный объект, созданный выражением a2.multiply(a5) будет уничтожено. Поэтому операторы удаления будут вызываться для указателей, копии которых назначены объекту a7. Кроме того, существует утечка памяти, поскольку исходные указатели объекта a7 не были удалены.

Вам необходимо явно определить оператор присваивания копии или оператор присваивания перемещения или оба.

...