#c #matrix
#c #матрица
Вопрос:
Итак, у меня есть простой класс matrix, и когда я регистрирую его на консоли, все в порядке, но проблема возникает при завершении программы.
Я не выделял никакой памяти кучи, это просто простой шаблонный класс, который может записывать матрицу в консоль. (Я планирую добавить сложение, вычитание и умножение.)
#include <iostream>
using std::cout, std::cin, std::ostream;
template<typename T = float, int R = 4, int C = R>
class Matrix {
public:
Matrix(T identity = T{}) {
for (int i = 0; i < R; i)
for (int j = 0; j < C; j)
matrix[i][j] = T{};
for (int i = 0; i < R; i)
matrix[i][i] = identity;
}
Tamp; operator()(int row, int column = 0) {
if (C == 1)
return matrix[(row < Ramp;amp; row > -1 ? row : 0)][0];
else
return matrix[(row < Ramp;amp; row > -1 ? row : 0)][(column < Ramp;amp; column > -1 ? column : 0)];
}
const Tamp; operator()(int row, int column = 0) const {
if (C == 1)
return matrix[(row < Ramp;amp; row > -1 ? row : 0)][0];
else
return matrix[(row < Ramp;amp; row > -1 ? row : 0)][(column < Ramp;amp; column > -1 ? column : 0)];
}
T* ToArray() {
return reinterpret_cast<T*>(matrix);
}
const T* ToArray() const {
return reinterpret_cast<const T* const>(matrix);
}
private:
T matrix[R][C];
};
template<typename T, int R = 4, int C = 0>
ostreamamp; operator<<(ostreamamp; stream, const Matrix<T, R, C>amp; matrix) {
const T* matrixArray = matrix.ToArray();
for (int i = 0; i < R; i) {
for (int j = 0; j < C; j) {
stream << (j == 0 ? '[' : ' ');
stream << matrix(i, j);
stream << (j == C - 1 ? ']' : ' ');
}
stream << (i == R - 1 ? '' : 'n');
}
return stream;
}
int main() {
Matrix a(1.0f);
Matrix<float, 4, 1> b(1.0f);
cout << a << 'n';
// no error occurs when I do this
//cout << b(1, 0) << 'n';
cout << b << 'n';
/* OUTPUT
[1 0 0 0]
[0 1 0 0]
[0 0 1 0]
[0 0 0 1]
[1]
[0]
[1]
[0]
*/
cin.get();
// when the error occurs
}
Комментарии:
1.
matrix[i][i] = identity;
Что, если матрица не квадратная?2. @dxiv Матрица 4 x 1 дает мне этот результат. /* [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1] [1] [0] [1] [0] */ По-моему, все в порядке.
3.
column < Ramp;amp; column > -1 ? column : 0)
это должно бытьcolumn < C
4. @xKaihatsu В матрице 4×1 нет элемента
matrix[1][1]
, но код записывается в нее независимо. Это переполнение буфера.5. @dxiv хороший улов, я добавлю это в ответ, если вы не возражаете
Ответ №1:
Проблема в этом цикле (благодаря dxiv)
for (int i = 0; i < R; i)
matrix[i][i] = identity;
доступ к массиву выходит за пределы, когда R> C, вы должны исключить этот цикл и изменить предыдущий (при условии, что логика всегда заполнять diagonal идентификатором в вашем коде верна):
for (int i = 0; i < R; i)
for (int j = 0; j < C; j)
matrix[i][j] = i == j ? identity : T{};
также в этом коде:
return matrix[(row < Ramp;amp; row > -1 ? row : 0)][(column < Ramp;amp; column > -1 ? column : 0)];
вы сравниваете column
с R
, но вы должны сравнивать с C
и, похоже, именно по этой причине вы обрабатываете регистр C==1
отдельно. Просто исправьте это, и вам больше не нужно это условие.
Примечание: я не вижу использования методов при reinterpret_cast
преобразовании массива в указатель, но, скорее всего, вы делаете что-то не так здесь.