【问题标题】:How to properly implement a copy constructor for a dynamic Matrix?如何正确实现动态矩阵的复制构造函数?
【发布时间】:2017-09-29 19:52:45
【问题描述】:

我有一个 Matrix (Matriz) 类实现如下:

标题:

#ifndef MATRIZ_H
#define MATRIZ_H


class Matriz
{
public:
    Matriz(unsigned int nL, unsigned int nC);
    ~Matriz();
    Matriz& operator+=(const Matriz &ptr);
    const Matriz operator+(const Matriz &ptr) const;
    Matriz* subtracaoMatriz(Matriz *m);
    Matriz* multiplicacaoMatriz(Matriz *m);
    void inserirMatriz();
    void imprimirMatriz();
    int verificaOperacao(const Matriz& ptr);
    Matriz& operator-=(const Matriz &ptr);
    const Matriz operator-(const Matriz &ptr) const;
    const Matriz operator*(const Matriz &ptr) const;

protected:

private:
    unsigned int nLinhas;
    unsigned int nColunas;
    int** matrix;
    int verificaOperacao(Matriz *m); //0 -> cannot make the operation; 1 -> OK for product; 2 -> OK for sum;

};

#endif // MATRIZ_H

实施:

#include "Matriz.h"
#include <iostream>

using namespace std;

Matriz::Matriz(unsigned int nL, unsigned int nC)
{
    this->nLinhas = nL;
    this->nColunas = nC;
    this->matrix = new int*[nLinhas];
    for (unsigned int i = 0; i < nLinhas; ++i)
        this->matrix[i] = new int[nColunas];
    for(unsigned int i = 0; i < nLinhas; i++)
        for(unsigned int j = 0; j < nColunas; j++)
            this->matrix[i][j] = 0;
}

Matriz::~Matriz()
{
    //dtor
}

int Matriz::verificaOperacao(Matriz *m)
{
    if((this->nLinhas == m->nLinhas) && (this->nColunas == m->nColunas))
        return 2;
    else if(this->nColunas == m->nLinhas)
        return 1;
    else
        return 0;
}

int Matriz::verificaOperacao(const Matriz& ptr)
{
    if((this->nLinhas == ptr.nLinhas) && (this->nColunas == ptr.nColunas))
        return 2;
    else if(this->nColunas == ptr.nLinhas)
        return 1;
    else
        return 0;
}

Matriz& Matriz::operator+=(const Matriz &ptr) {

    if(this->verificaOperacao(ptr) == 2)
    {
        for(unsigned int i = 0; i < this->nLinhas; i++)
            for(unsigned int j = 0; j < this->nColunas; j++)
                this->matrix[i][j] = this->matrix[i][j] + ptr.matrix[i][j];
        return *this;
    }
    else
        return *this;
}

const Matriz Matriz::operator+(const Matriz &ptr) const {
    Matriz resultado = *this;
    resultado += ptr;
    return resultado;
}


Matriz& Matriz::operator-=(const Matriz &ptr) {
    if(this->verificaOperacao(ptr) == 2)
    {
        for(unsigned int i = 0; i < this->nLinhas; i++)
            for(unsigned int j = 0; j < this->nColunas; j++)
                this->matrix[i][j] = this->matrix[i][j] - ptr.matrix[i][j];
        return *this;
    }
    else
        return *this;
}

const Matriz Matriz::operator-(const Matriz &ptr) const {
    Matriz resultado = *this;
    resultado -= ptr;
    return resultado;
}

const Matriz Matriz::operator*(const Matriz &ptr) const {
    Matriz *resultado = new Matriz(this->nLinhas, ptr.nColunas);
    for(unsigned i = 0; i < this->nLinhas; i++)
    {
        for(unsigned j = 0; j < ptr.nColunas; j++)
            for(unsigned int aux = 0; aux < ptr.nColunas; aux++)
                resultado->matrix[i][j] += this->matrix[i][aux] * ptr.matrix[aux][j];
    }
    return *resultado;
}

void Matriz::inserirMatriz()
{
    for(unsigned int i = 0; i < this->nLinhas; i++)
        for(unsigned int j = 0; j < this->nColunas; j++)
            cin >> this->matrix[i][j];
}

void Matriz::imprimirMatriz()
{

    for(unsigned int i = 0; i < this->nLinhas; i++) {
        for(unsigned int j = 0; j < this->nColunas; j++)
            cout << this->matrix[i][j] << "\t";
        cout << endl;
    }
}

主要:

#include <iostream>
#include "Matriz.h"

using namespace std;

int main()
{
    Matriz *m1 = new Matriz(2, 2);
    Matriz *m2 = new Matriz(2, 2);
    m1->inserirMatriz();
    m2->inserirMatriz();
    cout << "Matrix 1:" << endl;
    m1->imprimirMatriz();
    cout << "Matrix 2:" << endl;
    m2->imprimirMatriz();
    Matriz m3 = *m1 + *m2;
    cout << "The sum is: " << endl;
    m3.imprimirMatriz();
    cout << "The subtraction is: " << endl;
    Matriz m4 = *m1 - *m2;
    m4.imprimirMatriz();
    cout << "The product is: " << endl;
    Matriz m5 = *m1 * *m2;
    m5.imprimirMatriz();
    ///HERE LIES THE PROBLEM
    m2 = m1;
    cout << "m2 = m1" << endl;
    cout << "m2:" << endl;
    m2->imprimirMatriz();
    cout << "*m1 += *m2" << endl;
    cout << "m2:" << endl;
    *m1 += *m2;
    m2->imprimirMatriz();

    delete m1;
    delete m2;
    return 0;
}

我相信这个问题是由默认的复制构造函数引起的,但是我尝试实现一个但没有成功。

【问题讨论】:

  • 什么是“问题”?问题是什么?
  • 如果你问我,问题是你没有明显的原因进行手动动态内存分配。为什么是 m1m2 指针?为什么不使用std::vector
  • 您说您认为问题来自默认的复制构造函数,但您没有说明问题是什么?
  • 您更改了标题,但我不明白代码的相关性。为动态矩阵实现复制构造函数的正确方法是:你没有,其他人已经为你做了,只需使用std::vector
  • 顺便说一句,您不需要 this-&gt; 语法。仅当参数名称与数据成员名称相同时才需要它。不使用this-&gt; 将节省您的打字时间。 :-)

标签: c++ pointers copy-constructor


【解决方案1】:

拷贝构造函数有两种实现方式:

方法一

使用std::vector 代替动态内存,这种方法消除了对自定义复制构造函数的需要并消除了内存泄漏的风险,请参阅here。我不会重写你的代码,而是做一些简单的事情来说明这一点:

// Header file
#include <vector>

class Matriz
{
  ...
  private:
    std::vector<std::vector<int>> matrix;
}

// CPP file
Matriz::Matriz(unsigned int nL, unsigned int nC)
{
  matrix.resize(nL, std::vector<int>(nC, 0));

  // You can now access items with matrix[x][y].
}

这个带有向量的方法是有效的,因为当你想复制你的Matriz 类时,vector 的复制构造函数会被自动调用。一切都为你完成。

方法二

如果你还想使用动态内存,那么你需要实现一个深拷贝构造函数:

//Header file.
class Matriz
{
  ...
  Matriz(const Matriz& m);
}

// CPP file
Matriz::~Matriz() { delete[] matrix; } // DO NOT FORGET THIS!!!

Matriz::Matriz(const Matriz& m)
{
  delete[] matrix;

  // Create the dynamic memory.
  int** matrix = new int*[m.nLinhas];
  for(int i = 0; i < m.nLinhas; ++i)
    matrix[i] = new int[nColunas];

  nLinhas = m.nLinhas;
  nColunas = m.Colunas;

  // Copy over the data.
  for(int l = 0; l < nLinhas; l++)
  {
    for(int c = 0; c < nColunas; c++)
    {
      matrix[l][c] = m.matrix[l][c];
    }
  }
}

对于赋值运算符operator=,您可以遵循相同的概念。如果可以的话,我建议使用vector,这将消除任何可能的泄漏问题,并且考虑到你正在做的事情,不会有任何速度损失问题。

【讨论】:

  • 您的方法 2 有问题,没有遵循良好的做法。例如,它不是异常安全的。 您可以考虑阅读 Meyers 和 Sutter 关于有效和卓越 C++ 的书籍!
猜你喜欢
  • 1970-01-01
  • 2017-08-02
  • 1970-01-01
  • 2021-12-13
  • 2019-03-31
  • 1970-01-01
  • 2012-08-24
  • 2018-09-03
相关资源
最近更新 更多