C++中使用代理类实现矩阵切片赋值失效问题求助
Let's break down exactly why your A(1, 1, 3, 3) = B assignment isn't modifying matrix A, then walk through the fixes.
The Core Issue: SubMatrix Is Modifying a Copy, Not the Original Matrix
The biggest problem is in your SubMatrix class: its _matrix member is a value type (Matrix<T>) instead of a reference to the original matrix. When you call A(1, 1, 3, 3), the SubMatrix constructor creates a full copy of A and stores it in _matrix. Any changes you make to this copy have zero effect on the original A matrix—this is why your output still shows all 1s.
Secondary Issues
There are a couple of other problems that would cause bugs even if you fixed the reference issue:
- Missing const correctness: Your
slicefunction andSubMatrix::operator=take non-const references, which prevents you from using const matrices or temporary objects. - No boundary checks: Your
slicefunction doesn't verify if the requested slice fits within the matrix bounds, or if the source matrix matches the slice size—this could lead to undefined behavior. - Inefficient copy logic: The original
Matrix::operator=uses a manual loop instead of leveraging standard library utilities likestd::copy.
Step-by-Step Fixes
1. Modify SubMatrix to Hold a Reference to the Original Matrix
Change the _matrix member to a reference, so operations affect the original matrix instead of a copy:
template <typename T> class SubMatrix { size_t _i, _j, _p, _q; Matrix<T>& _matrix; // Store a reference to the original matrix, not a copy public: // Initialize the reference in the member initializer list 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) {} // Use const reference for the assignment parameter to support const matrices SubMatrix<T>& operator=(const Matrix<T>& matrix) { _matrix.slice(_i, _j, _p, _q, matrix); return *this; } };
2. Fix the Matrix::slice Function
Update slice to use const references for the source matrix, add boundary checks, and clean up the logic:
void slice(const size_t i, const size_t j, const size_t p, const size_t q, const Matrix<T>& other) // Const reference for the source matrix { // Add boundary checks to prevent out-of-bounds access if (i + p > _rows || j + q > _cols) { throw std::out_of_range("Slice exceeds matrix bounds"); } if (p != other._rows || q != other._cols) { throw std::invalid_argument("Source matrix size doesn't match slice size"); } size_t cont = 0; for (size_t ii = i; ii < i + p; ++ii) { for (size_t jj = j; jj < j + q; ++jj) { const size_t index = _cols * ii + jj; _matrix[index] = other._matrix[cont]; ++cont; } } }
3. Improve Matrix Class Correctness and Efficiency
Fix the copy constructor and assignment operator to use const references, add self-assignment checks, and use standard library functions:
// Updated copy constructor (const reference parameter) Matrix(const Matrix<T>& other) : _matrix(other._matrix), _rows(other._rows), _cols(other._cols) {} // Updated assignment operator Matrix<T>& operator=(const Matrix<T>& other) { // Avoid self-assignment if (this == &other) { return *this; } // Resize if the target matrix has a different size if (_rows != other._rows || _cols != other._cols) { _matrix.resize(other._matrix.size()); _rows = other._rows; _cols = other._cols; } // Use std::copy for efficient element copying std::copy(other._matrix.begin(), other._matrix.end(), _matrix.begin()); return *this; } // Make print a const member function (it doesn't modify the matrix) void print() const { 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'; } }
Test the Fixed Code
When you run your main.cpp with these changes, the output will now show the expected slice assignment:
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 9 9 9 9 9 9 9 9 9 1 1 1 1 1 1 9 9 9 1 1 9 9 9 1 1 9 9 9 1 1 1 1 1 1
内容的提问来源于stack exchange,提问作者user12422568

