Свой оператор присваивания и перемещения для векторной матрицы

Задание состоит в том чтобы составить описание класса, обеспечивающего представление матрицы произвольного размера с возможностью вывода на экран подматрицы любого размера и всей матрицы. В классе должны быть следующие функции:

  1. конструктор по умолчанию;
  2. конструктор копирования (copy constructor);
  3. конструктор перемещения (move constructor);
  4. оператор присваивания (copy assignment);
  5. оператор перемещения (move assignment);
  6. функция вывода на экран всей матрицы;
  7. деструктор (destructor).

Вот реализация класса Matrix:

class Matrix{
private:
    vector<int> arr;
    vector<vector<int>> *mat = new vector<vector<int>>;
public:
    Matrix(){}
    Matrix(int x, int y){
        for (int i = 0; i < x; i++){
            for (int j = 0; j < y; j++)
                arr.push_back(rand() % 89 + 10);
            mat->push_back(arr);
            arr.clear();
        }
    }
    Matrix(const Matrix& matx){
        cout << "copy" << endl;
        mat = new vector<vector<int>>;
        mat->assign(matx.mat->begin(), matx.mat->end());
    }

    Matrix(Matrix&& matx){
        cout << "move" << endl;
        mat->assign(matx.mat->begin(), matx.mat->end());
        matx.mat->clear();
    }

    Matrix& operator=(const Matrix& matx){
        delete mat;
        cout << "copy0" << endl;
        mat->assign(matx.mat->begin(), matx.mat->end());
        return *this;
    }

    Matrix& operator=(Matrix&& matx){
        cout << "move0" << endl;
        delete mat;
        mat->assign(matx.mat->begin(), matx.mat->end());
        matx.mat->clear();
        return *this;
    }

    void out(){
        for (int i = 0; i < int(mat->size()); i++){
            for (int j = 0; j < int((*mat)[i].size()); j++)
                cout << (*mat)[i][j] << " ";
            cout << endl;
        }
        cout << endl;
    }

    ~Matrix(){
        delete mat;
        arr.clear();
    }
};

Конструкторы копирования работают нормально. А вот операторы присваивания и перемещения выдают ошибку:

Первый этап обработки исключения по адресу 0x0FE6DF58 (msvcp120d.dll) в ConsoleApplication8.exe: 0xC0000005: нарушение прав доступа при чтении по адресу 0xFEEEFEF2.

Тело программы:

void main()
{
    Matrix m1(2, 3), m2(m1), m3(move(m1)), m4;
    m1.out();
    m2.out();
    m3.out();
    m1 = *new Matrix(3, 2);
    m4 = move(m3);
    m1.out();
    m3.out();
    m4.out();
    _getch();
}

Ответы (1 шт):

Автор решения: Harry

Для начала я бы перенес

vector<int> arr;

в единственный конструктор, где этот вектор используется, и не хранил бы его в классе. Зачем?...

Далее, перемещение - это и есть перемещение, а не копирование:

Matrix(Matrix&& matx)
{
    cout << "move" << endl;
    mat = matx.mat;
    matx.mat = nullptr;
}

Оператор присваивания вообще уникален...

Matrix& operator=(const Matrix& matx){
    delete mat;        
    cout << "copy0" << endl;
    mat->assign(matx.mat->begin(), matx.mat->end());
    return *this;
}

После удаления во второй строке mat - что вы пытаетесь делать с ним? Какое

    mat->assign(matx.mat->begin(), matx.mat->end());

??? И с перемещающим оператором присваивания проблемы:

Matrix& operator=(Matrix&& matx)
{
    delete mat;
    mat = matx.mat;
    matx.mat = nullptr;
    return *this;
}

Словом, я бы делал так:

class Matrix
{
private:
    vector<vector<int>> *mat = nullptr;
public:
    Matrix(){}
    Matrix(int x, int y)
    {
        mat = new vector<vector<int>>;
        for (int i = 0; i < x; i++)
        {
            vector<int> arr;
            for (int j = 0; j < y; j++)
                arr.push_back(rand() % 89 + 10);
            mat->push_back(arr);
        }
    }
    Matrix(const Matrix& matx)
    {
        cout << "copy" << endl;
        mat = new vector<vector<int>>;
        *mat = *matx.mat;
    }

    Matrix(Matrix&& matx)
    {
        cout << "move" << endl;
        mat = matx.mat;
        matx.mat = nullptr;
    }

    Matrix& operator=(const Matrix& matx)
    {
        delete mat;
        cout << "copy0" << endl;
        mat = new vector<vector<int>>;
        *mat = *matx.mat;
        return *this;
    }

    Matrix& operator=(Matrix&& matx)
    {
        delete mat;
        mat = matx.mat;
        matx.mat = nullptr;
        return *this;
    }

    void out()
    {
        if (!mat)
        {
            cout << "No matrix\n";
            return;
        }
        for (int i = 0; i < mat->size(); i++)
        {
            for (int j = 0; j < (*mat)[i].size(); j++)
                cout << (*mat)[i][j] << " ";
            cout << endl;
        }
        cout << endl;
    }

    ~Matrix()
    {
        delete mat;
    }
};


int main()
{
    Matrix m1(2, 3), m2(m1), m3(move(m1)), m4;
    m1.out();
    m2.out();
    m3.out();
    Matrix * tmp = new Matrix(3, 2);
    m1 = *tmp;
    delete tmp;
    m4 = move(m3);
    m1.out();
    m3.out();
    m4.out();
}
→ Ссылка