1

Below is the snippet of code where the error lies, the line

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

returns an error

lvalue required as left operand of assignment

I can't find an answer that applies to arrays, my Matrix is defined as follows:

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;
}

Here is the operator[] How do I return by reference

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[]両方で、参照によって返されるように実装を変更する必要があります。参照によって返される関数呼び出しは左辺値式であり、それに割り当てることができます。MatrixMatrix::operator[]

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

もちろん、これは理にかなっています。あなたoperator[]の が参照によって返されなかった場合、それらによって返された値に代入すると、の内容にどのような影響がありMatrixますか?


あなたの編集に応じて:

クラスの設計に問題があります。このクラスは、と呼ばれる のMatrix3 行 3 列の配列を格納しているように見えます。ただし、 を使用すると、 の行からオブジェクトに値がコピーされます。それらはコピーです。次に、それを値で返します。これにより、とそれに含まれる値が関数からコピーされます。返されたものに対して行うことは、そのコピーにのみ影響します。floatcoordsMatrix::operator[]coordsVectorVectorVectorVector

これに加えて、あなたのswitch発言はまったく無意味です。どのケースもまったく同じです。i配列インデックスとして使用するだけで、スイッチを入れる必要はありません。

また、 を呼び出す人がoperator[]の内容を変更できるようにするMatrix場合、operator[]関数は であってはなりませんconst

問題を解決するいくつかの代替手段があります。1 つ目は、代わりに a を返し、次のfloat*ように計画を破棄することVectorです。

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

これは非常に単純な解決策ですが、生のポインターを渡す必要があります。生のポインターは配列のように使用できるため、次の構文を使用できますm[i][j]

Eigen ライブラリと同じことを行い、代わりoperator()に行インデックスと列インデックスの 2 つの引数を取る を提供できます。

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[] ます。[][]構文が機能するには、2 番目の構文を適用できるある種のプロキシを返す必要があり、マトリックス内の目的の要素への参照を返します。[](少なくとも私にとっては)これを行う通常の方法は、で「セッター」と「ゲッター」を定義することです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 ) ];
}

次に、2 つのプロキシ (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をとしても使用する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]、これは最初に float ポインターにmat[x]アクセスし、次にyその列の -th 要素 (左辺値) にアクセスします。

于 2013-02-12T13:19:15.513 に答える