c++ - 通过重载下标运算符()从矩阵获取 vector

标签 c++ vector matrix operator-overloading

我想做这样的事情:

Matrix m;    // (4x4 matrix)
Vector4 v;   // (4-elements vector)

m(0) = v;    // replace first 4-elements matrix row by vector v
v = m(0);    // replace vector v by first 4-elements matrix row

这是我的代码:

Vector4& Matrix::operator() (unsigned row)
{
    return Vector4(mat[row][0], mat[row][1], mat[row][2], mat[row][3]);
}

Vector4 Matrix::operator() (unsigned row) const
{
    return Vector4(mat[row][0], mat[row][1], mat[row][2], mat[row][3]);
}

第二个运算符工作正常,但是当我尝试编译第一个运算符时,出现此错误:

错误:从“Vector4”类型的右值对“Vector4&”类型的非常量引用进行无效初始化

那么问题出在哪里呢?在这种情况下,重载operator()而不是operator[]是个好主意吗?

通过仅从矩阵中获取一个元素,我使用了其他两个运算符:

float& Matrix::operator() (unsigned row, unsigned col)
{
    return mat[row][col];
}

float Matrix::operator() (unsigned row, unsigned col) const
{
    return mat[row][col];
}

编辑1(几乎是解决方案)

我想我找到了一些解决方案。第一个运算符已替换为:

Matrix::MatrixHelper operator() (unsigned row)
{
    MatrixHelper m;
    m.f1 = &mat[row][0];
    m.f2 = &mat[row][1];
    m.f3 = &mat[row][2];
    m.f4 = &mat[row][3];

    return m;
}

这是 MatrixHelper 类的定义:

class MatrixHelper
{
    public:

    friend class Matrix;

    void operator= (const Vector4& v)
    {
        *f1 = v.x;
        *f2 = v.y;
        *f3 = v.z;
        *f4 = v.w;
    }

    private:

    float* f1;
    float* f2;
    float* f3;
    float* f4;
};

现在可以做这样的事情:

m(0) = Vector4(3,3,3,3);

但是调用此方法时会出现新问题:

(m)(0) * someScalar;

第二个运算符永远不会被调用,所以我必须在我的 MatrixHelper 类中实现它们,对吗?我走在正确的道路上吗?

编辑 2

好的,如果两个运算符(operator)同时工作,这个问题就可以解决。但现在只能启用其中之一。我不明白为什么总是在第一个操作符上工作,例如有这个代码(只是示例):

Vector4& Matrix::operator() (unsigned row)
{
    std::cout << "Operator one is working now\n";
}

Vector4 Matrix::operator() (unsigned row) const
{
    std::cout << "Operator two is working now\n";
}

不管我在做什么

m(0) = Vector(4,4,4,4)

Vector4 v = m(0)

始终是第一个运算符(operator)工作。为什么?

编辑 3(解决方案)

我找到了其他解决方案。现在一切都正常了,但性能可能有点问题。解决方案没有按照我想要的方式解决,而且有点牵强。代码如下:

运营商:

Vector4 Matrix::operator() (unsigned row)
{
    return Vector4 (&mat[row][0], &mat[row][1], &mat[row][2], &mat[row][3]);
}

Vector4 Matrix::operator() (unsigned row) const
{
    return Vector4 (mat[row][0], mat[row][1], mat[row][2], mat[row][3]);
}

如您所见,第一个运算符返回一个带有指针的 vector 。艰苦的工作现在发生在 Vector4 类而不是 Matrix 中。 Vector4 现在有一个额外的构造函数:

Vector4(float* x, float* y, float* z, float* w)
{
    this->px = x; this->py = y; this->pz = z; this->pw = w;
    this->x = *x; this->y = *y; this->z = *z; this->w = *w;
    pointer = true;
}

第一行是指针,第二行是变量,第三行是 bool 类型变量,这意味着调用了什么构造函数(普通或指针)。

现在是最后一个运算符(operator=):

Vector4 operator= ( const Vector4& v)
{
    if ( pointer )
    {
        *px = x = v.x;
        *py = y = v.y;
        *pz = z = v.z;
        *pw = w = v.w;
    }
    else
    {
        x = v.x;
        y = v.y;
        z = v.z;
        w = v.w;
    }
}

如果pointer为真,则意味着 - pxpypzpw 是指向矩阵中某些行元素的指针,我们必须更改它们。否则 - 只是法 vector 。

所以现在问题...这是糟糕的解决方案,还是只是糟糕? :D

最佳答案

您在错误代码中实例化的 Vector4 是一个临时的右值。除了不能将其分配给非常量引用这一事实之外,当函数退出时它将被销毁,并且返回值将是无效的堆栈位置。

一种解决方案是按值返回不同的对象,该对象存储对您需要的各个元素的引用,并允许您以透明的方式对它们进行操作。

关于c++ - 通过重载下标运算符()从矩阵获取 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17177296/

相关文章:

Boost.Fusion 中的 C++ 可变参数宏?

c++ - 声明一个 union 指针,里面有一个指针

python - 在 python 中生成陆地多边形

c++ - 非常大的A分界线在非常大的B处

python - 矩阵中对角线元素的总和

c++ - 使用带有CMake和Clang的GraphViz的Callgraphs

c++ - vector/算法与 iostream 之间的不兼容性

php - 如何将 N 个向量的每个元素相乘 N^N 次

c++ - 用于 OpenGL 的轻量级数学库

python - 计算按前两列中的索引分组的 numpy 数组条目的第 N 列的总和?