0

每当我将一个已经声明的东西分配Matrix给其他东西时,我的程序就会意外退出。

我真的不知道为什么会发生这种情况,我的印象是让编译器生成赋值运算符是最好的事情,除非你绝对必须重载它,这让我觉得我的构造函数或其他东西有问题?

例子:

Matrix rotation = rotationMatrix3(Y, degToRad(20.0f));
Vector3 left = rotation * direction_;

rotation = rotationMatrix3(Y, degToRad(-20.0f)); //crash
Vector3 right = rotation * direction_;

这是我的矩阵类:

矩阵.h

enum Axis {
    X, Y, Z,
};

class Matrix {
public:
    Matrix(int cols, int rows);
    Matrix(int cols, int rows, const float values[]);
    ~Matrix();

    float& operator()(int col, int row);
    float  operator()(int col, int row) const;
    inline int cols() const { return cols_; }
    inline int rows() const { return rows_; }

private:
    int cols_, rows_;
    float* values_;
};

Vector3 operator*(const Matrix& m, const Vector3& v);

Matrix rotationMatrix3(int axis, float rads);

矩阵.cpp

Matrix::Matrix(int cols, int rows) : cols_(cols), rows_(rows), values_(NULL) {
    values_ = new float[rows_ * cols_];
}

Matrix::Matrix(int cols, int rows, const float values[]) : cols_(cols), rows_(rows), values_(NULL) {
    values_ = new float[rows_ * cols_];

    for(int c = 0; c < cols; ++c) {
        for(int r = 0; r < rows; ++r) {
            (*this)(c, r) = values[r * cols + c];
        }
    }
}

Matrix::~Matrix() {
    delete [] values_;
}

float& Matrix::operator()(int col, int row) {
    return values_[row * cols_ + col];
}

float Matrix::operator()(int col, int row) const {
    return values_[row * cols_ + col];
}

Vector3 operator*(const Matrix& m, const Vector3& v) {
    if(m.cols() != 3) {
        throw std::logic_error("Matrix must have only 3 cols");
    }

    Vector3 result;
    result.x = m(0, 0) * v.x + m(1, 0) * v.y + m(2, 0) * v.z;
    result.y = m(0, 1) * v.x + m(1, 1) * v.y + m(2, 1) * v.z;
    result.z = m(0, 2) * v.x + m(1, 2) * v.y + m(2, 2) * v.z;

    return result;
}

Matrix rotationMatrix3(int axis, float rads) {
    float c = static_cast<float>(cos(rads));
    float s = static_cast<float>(sin(rads));

    if(axis == X) {
        const float mat[] = { 1.0f, 0.0f, 0.0f,
                              0.0f, c,    -s,
                              0.0f, s,    c };
        return Matrix(3, 3, mat);
    } else if(axis == Y) {
        const float mat[] = { c,    0.0f, s,
                              0.0f, 1.0f, 0.0f,
                              -s,   0.0f, c };
        return Matrix(3, 3, mat);
    } else if(axis == Z) {
        const float mat[] = { c,    -s,   0.0f,
                              s,    c,    0.0f,
                              0.0f, 0.0f, 1.0f };
        return Matrix(3, 3, mat);
    } else {
        throw std::logic_error("Unknown axis");
    }
}
4

2 回答 2

2

是的,制作一个带有矩阵的复制构造函数。否则,您将复制values_随后在立即超出范围的原始返回值中删除的指针。

我对你的建议......你显然是在创建类来做 3D。不要为此创建任意大小的矩阵类。只需制作一个基本的 4x4 齐次矩阵(或 4x3 或 3x3,如果必须)。硬编码。单个值数组 - 没有动态分配。为您节省大量时间、堆碎片和烦人的健全性测试。你永远不会用 5x17 矩阵或其他什么来运行这个类。所以不要为它编码。

您通常需要 2d、3d 或 4d 向量以及 3d 或 4d 方阵。就这样。所以让你的课程:

Vector2
Vector3
Vector4
Matrix3
Matrix4
于 2012-07-30T23:30:44.290 回答
2

我的印象是让编译器生成赋值运算符是最好的做法,除非你绝对必须重载它,这让我觉得我的构造函数有什么问题?

放下那个印象。语言中的那些免费赠品很少是“正确”的事情。您的班级中有一个原始指针float* values_;。您绝对必须在此处重载复制构造函数和赋值运算符。

于 2012-07-30T23:34:20.423 回答