1

下面是错误所在的代码片段,该行

a[i][j] = m[i][j] + w[i][j];

返回错误

左值需要作为赋值的左操作数

我找不到适用于数组的答案,我的矩阵定义如下:

Matrix::Matrix() {
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            coords[i][j] = 0.0f;
}

const Matrix operator+(const Matrix &m, const Matrix &w) {
    Matrix a;
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 4 ; j++)
            a[i][j] = m[i][j] + w[i][j];  // <----- error
    return a;
}

这里是 operator[] 我如何通过引用返回

const Vector Matrix::operator[](int i) const{
    switch(i)
    {
    case 0: return Vector (coords[i][0], coords[i][1], coords[i][2]);
    case 1: return Vector (coords[i][0], coords[i][1], coords[i][2]);
    case 2: return Vector (coords[i][0], coords[i][1], coords[i][2]);
    }
}
4

4 回答 4

13

错误实际上是“需要左值作为赋值的左操作数”。

这意味着您a[i][j]正在给您一个临时对象。当您按值从函数返回时会发生这种情况。按值返回的函数调用是右值表达式,不能将右值表达式用作赋值的左操作数。您需要更改返回operator[]的 theMatrix和 helper 类的实现,Matrix::operator[]以便它们通过引用返回。通过引用返回的函数调用是一个左值表达式,并允许您分配给它。

template <typename T>
Vector<T>& Matrix<T>::operator[](int index) { ... }
template <typename T>
T& Vector<T>::operator[](int index) { ... }

当然,这是有道理的。如果您operator[]的 s 没有通过引用返回,那么分配给它们返回的值对 s 的内容有何影响Matrix


回应您的编辑:

你的班级设计有问题。该类Matrix似乎存储了一个float名为 s的 3×3 数组coords。但是,当您使用 时Matrix::operator[],它将值从一行复制coords到一个Vector对象中。它们是副本。然后Vector按值返回它,这会将 和它包含的值复制Vector到函数之外。您对返回的任何操作Vector都只会影响该副本。

除此之外,你的switch说法完全没有意义。每个案例都完全相同。您只需要i用作数组索引而不是打开它。

另外,如果您要允许调用operator[]的人修改您的内容Matrix,则该operator[]函数不能是const.

有一些替代方案可以解决您的问题。第一个是只返回 afloat*并取消您的计划Vector

float* Matrix::operator[](int i) {
    return coords[i];
}

这是一个非常简单的解决方案,但确实涉及传递一个原始指针。原始指针可以像数组一样使用,允许您使用m[i][j].

您可以执行与 Eigen 库相同的操作,而是提供带有operator()两个参数的 a,即行索引和列索引:

float& Matrix::operator()(int i, int j) {
    return coords[i][j];
}

请注意,float正在通过引用返回:float&. 这意味着可以从调用外部修改operator(). 在这里,您将使用m(i, j).

于 2013-02-12T12:45:01.440 回答
1

这意味着您的[]运算符返回一个没有地址的值,该地址不能用于赋值。它直截了当。

于 2013-02-12T12:45:34.480 回答
1

是什么Vector

问题可能从Matrix::operator[] 返回的内容开始。为了使[][]语法起作用,它必须返回某种代理,[]可以应用第二种代理,并且它将返回对矩阵中所需元素的引用。这样做的通常方法(至少对我而言)是在以下位置定义一个“setter”和“getter” Matrix

void set( int i, int j, double new_value )
{
    myData[ getIndex( i, j ) ] = new_value;
}

double get( int i, int j ) const
{
    return myData[ getIndex( i, j ) ];
}

然后使用两个代理(Matrix 中的嵌套类):

class Proxy2D
{
    Matrix* myOwner;
    int myIndex1;
    int myIndex2;
public:
    Proxy2D( Matrix& owner, int index1, int index2 )
        : myOwner( &owner )
        , myIndex1( index1 )
        , myIndex2( index2 )
    {
    }
    void operator=( double new_value ) const
    {
        myOwner->set( myIndex1, myIndex2, new_value ):
    }
    operator double() const
    {
        return myOwner->get( myIndex1, myIndex2 );
    }
};

class Proxy1D
{
    Matrix* myOwner;
    int myIndex;
public:
    Proxy1D( Matrix& owner, int index )
        : myOwner( &owner )
        , myIndex( index )
    {
    }
    Proxy2D operator[]( int index2 ) const
    {
        return Proxy2D( *myOwner, myIndex, index2 );
    }
};

Proxy1D operator[]( int index1 )
{
    return Proxy1D( *this, index1 );
}

在实践中,您还希望 const 变体由operator[]( int index1 ) const. 当然, ConstProxy2D不需要重载operator=; 隐式转换就足够了。

如果不明显,Matrix::getIndex请进行边界检查,然后计算 std::vector<double>包含数据的底层证券中的实际索引。

于 2013-02-12T13:25:05.587 回答
0

由于您返回一个新构造的Vector对象来表示一列(或行,并不重要),这个 Vector 负责更新原始 Matrix 实例中的一个条目,这有点棘手但很容易解决:

您必须实现另一个VectorRef类,该类不按值表示向量,而是按引用表示,因此可用于以lvalues的形式访问组件。这意味着,它不包含作为值的数字,而是作为引用,并在其构造函数中获取这些引用。为简单起见,您可以使用指向第一个组件(后跟其他组件)的指针:

class VectorRef {
    float *coords;
public:
    VectorRef(float *coords) : coords(coords) {}
    float & operator[](int i) { return coords[i]; }
};

operator[]然后,在矩阵中构造这样一个“参考对象” :

VectorRef Matrix::operator[](int i) {
    return VectorRef (coords[i]);
}

要将VectorRef也用作 a Vector,请提供转换运算符:

    // (within VectorRef:)
    operator Vector() const { return Vector(coords[0], coords[1], coords[2]); }

这应该使事情变得无懈可击。

或者,如果您总是访问矩阵中的元素而不是整个列,只需直接在operator[]矩阵中返回列指针:

float * Matrix::operator[](int i) {
    return coords[i];
}

写入时mat[x][y],这将首先访问浮点指针,mat[x]然后访问该y列的第 - 个元素,即左值

于 2013-02-12T13:19:15.513 回答