在C++中使用代理类对矩阵类中的矩阵进行切片和赋值

q9yhzks0  于 2023-01-18  发布在  其他
关注(0)|答案(2)|浏览(205)

我希望有一个简单的矩阵类,它具有切片功能,以避免嵌套的for循环。

// matrix.hpp

#include <cstddef>
#include <iostream>
#include <vector>

template <typename T>
class SubMatrix;

template <typename T>
class Matrix
{
    std::vector<T> _matrix;
    size_t _rows;
    size_t _cols;

public:
    Matrix(const size_t rows, const size_t cols) : _matrix(rows * cols),
                                                   _rows(rows),
                                                   _cols(cols) {}

    Matrix(const size_t rows, const size_t cols, const T init)
        : _matrix(rows * cols, init),
          _rows(rows),
          _cols(cols) {}

    Matrix(Matrix &other) : _matrix(other._matrix),
                            _rows(other._rows),
                            _cols(other._cols) {}

    ~Matrix() {}

    Matrix &operator=(Matrix &other)
    {
        for (size_t i = 0; i < _matrix.size(); ++i)
            _matrix[i] = other._matrix[i];

        _rows = other.rows();
        _cols = other.cols();

        return *this;
    }

    T operator()(const size_t i, const size_t j) const
    {
        return _matrix.at(_cols * i + j);
    }

    T &operator()(const size_t i, const size_t j)
    {
        return _matrix.at(_cols * i + j);
    }

    /*
        i, j: initial row and column, respectively
        p: number of rows from i
        q: number of columns from j
    */

    void slice(const size_t i, const size_t j,
               const size_t p, const size_t q,
               Matrix &other)
    {
        size_t index{0};
        size_t cont{0};

        for (size_t ii = i; ii < i + p; ii++)
        {
            for (size_t jj = j; jj < j + q; jj++)
            {
                index = _cols * ii + jj;
                _matrix[index] = other._matrix[cont];

                ++cont;
            }
        }
    }

    void print()
    {
        std::cout << '\n';
        for (size_t i = 0; i < _rows; ++i)
        {
            for (size_t j = 0; j < _cols; ++j)
                std::cout << this->operator()(i, j) << ' ';

            std::cout << '\n';
        }
    }

    SubMatrix<T> operator()(const size_t i,
                            const size_t j,
                            const size_t p,
                            const size_t q)
    {
        SubMatrix<T> sub_matrix(i, j, p, q, *this);
        return sub_matrix;
    }
};

要使切片特征为

A(i, j, p, q) = B

其中AB是矩阵,ij是初始索引,pqi的行数,qj的行数,我编写了以下代理类

template <typename T>
class SubMatrix
{
    size_t _i, _j, _p, _q;

public:
    Matrix<T> _matrix;

    SubMatrix(const size_t i,
              const size_t j,
              const size_t p,
              const size_t q,
              Matrix<T> &matrix) : _i(i),
                                   _j(j),
                                   _p(p),
                                   _q(q),
                                   _matrix(matrix) {}

    SubMatrix<T> &operator=(Matrix<T> &matrix)
    {
        _matrix.slice(_i, _j, _p, _q, matrix);
        return *this;
    }
};

代码运行顺利,但切片执行不正确。矩阵B未分配给A

// main.cpp

#include "matrix.h"

int main()
{
    Matrix<double> A(5, 5, 1.0);
    Matrix<double> B(3, 3, 9.0);

    A.print();

    B.print();

    A(1, 1, 3, 3) = B;
    A.print();

    return 0;
}

代码的输出为:
有人知道为什么B的值没有被赋给A吗?

stszievb

stszievb1#

SubMatrix<T> Matrix::operator()创建其内部成员_matrix的临时副本,然后通过来自B的赋值修改此副本。
但是原始的A保持不变,当你使用reference时,赋值运算符将赋值给原始的_matrix成员:

template <typename T>
class SubMatrix
{
// ...
    Matrix<T> &_matrix;
public:
// ...
};

不相关,但_matrix应为私有成员。

toiithl6

toiithl62#

你的代码基本上是这样的:

#include <iostream>

struct Proxy { int x; };

struct twoNumbers { 
    int a = 0;
    int b = 0;
    Proxy aset() {return {a};}
    Proxy bset() {return {b};}
};

int main() {
    twoNumbers A;
    auto p = A.aset();
    p.x = 42;
    std::cout << A.a;
}

Proxy存储该值的副本,修改该副本不会影响原始值。
我们需要的是Proxy持有一个允许修改原始文件的引用。

#include <iostream>

struct Proxy { int& x; };

struct twoNumbers { 
    int a = 0;
    int b = 0;
    Proxy aset() {return {a};}
    Proxy bset() {return {b};}
};

int main() {
    twoNumbers A;
    auto p = A.aset();
    p.x = 42;
    std::cout << A.a;
}

output

42

相关问题