矩阵分配导致崩溃

时间:2012-07-30 23:08:44

标签: c++ assignment-operator

每当我将已经声明的Matrix分配给somethnig,我的程序意外退出。

我真的不知道为什么会发生这种情况,我的印象是让编译器生成赋值运算符是最好的事情,除非你绝对不得不重载它,这让我觉得我的错了构造函数还是什么?

示例:

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

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

这是我的Matrix课程:

Matrix.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);

Matrix.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");
    }
}

2 个答案:

答案 0 :(得分:2)

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

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

您通常需要2d,3d或4d矢量以及3d或4d方阵。就这样。所以上课:

Vector2
Vector3
Vector4
Matrix3
Matrix4

答案 1 :(得分:2)

  

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

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