1

私は本インタラクティブコンピュータグラフィックスを使用してコンピュータグラフィックスを学ぼうとしています-トップダウンアプローチ、例のコードはこのリンクにあります

いくつかのマトリックスユーティリティを提供する「mat.h」というヘッダーライブラリがありますが、Xcodeでコンパイルしようとすると、次のエラーがスローされます。

タイプ'Angel::mat2'への非定数左辺値参照はタイプ'Angel::mat2'の一時的なものにバインドできません

そのエラーをスローするコードは次のとおりです。

mat2& operator /= ( const GLfloat s ) {
#ifdef DEBUG
    if ( std::fabs(s) < DivideByZeroTolerance ) {
        std::cerr << "[" << __FILE__ << ":" << __LINE__ << "] "
                  << "Division by zero" << std::endl;
        return mat2();
    }
#endif // DEBUG

アプリのデバッグ時にコンパイルされるだけなのでコメントアウトしますが、何が問題なのか、どうやって解決するのか知りたいです。

4

2 に答える 2

6

厳密に言えば、エラーの正式な理由は非定数参照を一時オブジェクトにバインドしようとすることですが、ここでの本当の問題は、参照、つまり一時オブジェクトへの参照を返そうとすることです参照がconstであるかどうかは関係ありません。

一時オブジェクトは、returnステートメントが完了した直後に破棄され、破棄されたオブジェクトにバインドされたぶら下がっている参照が返されます。つまり、returntypeをconstreferenceに変更してこのコードを「修正」しようとしても、正しく機能しません。

さらに、設計上、この関数は非定数参照を返すことになっているようです。つまり、この関数の戻り型を変更することはオプションではありません。非定数参照は、複合代入演算子が通常返すものです。「ゼロ除算」の状況の場合、デバッグブランチは早期に終了する(そしてもちろん、コードをコンパイルするためだけに何かを返す)ことになっています。

これを実現する1つの方法は、タイプのスタンドアロンオブジェクトを(たとえばmat2、クラスの静的メンバーとして)宣言し、そのオブジェクトへの参照を返すことです。mat2つまり、宣言します

class mat2 {
  ...
#ifdef DEBUG
  static mat2 bad_result;
#endif // DEBUG
};

それを定義する

#ifdef DEBUG
mat2 mat2::bad_result;
#endif // DEBUG

そしてします

return bad_result;

エラーが検出されたときはいつでも。

returnあるいは(そしてはるかに簡単に)、そのステートメントの直前にローカルで宣言することができます

#ifdef DEBUG
    if ( std::fabs(s) < DivideByZeroTolerance ) {
        std::cerr << "[" << __FILE__ << ":" << __LINE__ << "] "
                  << "Division by zero" << std::endl;
        static mat2 bad_result;
        return bad_result;
    }
#endif // DEBUG

もちろん、この設計には明らかな欠陥があります。これは、外部コードが返されたオブジェクトを変更できるため、望ましくありません。ただし、エラーメッセージが出力されると、プログラムの動作は保証されないという考えが考えられますstd::err。つまり、この場合、戻り値の変更可能性は問題になりません。

その最後の点を考慮に入れると、非静的ローカル変数を戻り値として使用することもできます

#ifdef DEBUG
    if ( std::fabs(s) < DivideByZeroTolerance ) {
        std::cerr << "[" << __FILE__ << ":" << __LINE__ << "] "
                  << "Division by zero" << std::endl;
        mat2 bad_result;
        return bad_result;
    }
#endif // DEBUG

ローカル変数への参照を返すことは、一時的なものへの参照を返すことと同じくらい間違っています(ほぼ同じ理由で)。ただし、「エラー後の保証なし」アプローチでは、「機能」します。つまり、エラーメッセージが修正されます。

于 2013-01-24T23:16:04.303 に答える
3

問題は、非左辺値参照が、右辺値constである一時的なものにバインドできないことです。左辺値参照(C++98およびC++11)または右辺値参照(C ++ 11のみ)のみが可能です。この演算子は、関数から戻ったときに作成された一時値への左辺値参照を返そうとしています。const

    mat2& operator /= ( const GLfloat s ) {
//  ^^^^^
//  RETURNS A NON-CONST LVALUE REFERENCE
        ...
        return mat2(); // <--- CREATES A TEMPORARY (RVALUE)
    }
于 2013-01-24T22:55:38.613 に答える