3

コピーコンストラクターに値を参照として渡していますが、無限ループが呼び出されています。

これが私のクラスです:

class Vector2f{
private:
    GLfloat x;
    GLfloat y;

public:
    Vector2f();
    Vector2f(const GLfloat _x, const GLfloat _y);
    Vector2f(const Vector2f &_vector);

    ~Vector2f();
};

メソッドの実装は次のとおりです。

Vector2f::Vector2f():
        x( 0.0f ),
        y( 0.0f )
{
    DebugLog("Vector2f constructor");
}

Vector2f::Vector2f(const GLfloat _x, const GLfloat _y):
        x( _x ),
        y( _y )
{
    DebugLog("Vector2f constructor(%f, %f)", _x, _y);
}


Vector2f::Vector2f(const Vector2f &_vector):
        x( _vector.getX() ),
        y( _vector.getY() )
{
    DebugLog("Vector2f copy constructor");
}

Vector2f::~Vector2f()
{

}

クラスにアクセスする方法は次のとおりです。

Vector2f tempVector1 = Vector2f(0.0f, 0.0f);
DebugLog("tempVector1 initialized");

Vector2f tempVector2;
tempVector2 = Vector2f(0.0f, 0.0f);
DebugLog("tempVector2 initialized");

私が得た結果は次のとおりです。

Vector2f constructor(0.000000, 0.000000)
tempVector1 initialized
Vector2f constructor
Vector2f constructor(0.000000, 0.000000)
Vector2f copy constructor
Vector2f copy constructor
Vector2f copy constructor
...

以前に作成されたオブジェクトを初期化しようとすると、無限ループが発生します。tempVector1をtempVector2にコピーしようとすると、無限ループも発生します。

Vector2f tempVector2;
tempVector2 = Vector2f(tempVector1);

なぜそれが起こるのですか、そしてどうすればそれが無限ループに入るのを防ぐことができますか?

前もって感謝します。

4

4 に答える 4

6

この行:

tempVector2 = Vector2f(tempVector1);

コピーコンストラクタではなく、operator=を呼び出します。何か風変わりなことをしているoperator=を定義していますか?

また、Linuxのg++4.3.2とMacのg++4.2.1の両方で、コードは正常に機能しました(getX、getYを定義し、DebugLogをprintfに変換し、GLfloatの代わりにfloatを使用した後)。

于 2010-01-28T08:43:53.033 に答える
1

問題は代入演算子にあると思います。operator =はどのように見えますか?

operator=は何らかの方法で彼を自分自身と呼んでいるようです。コードスニペットがoperator=自体の本体から取得される可能性はありますか?

その場合の解決策は、コピーコンストラクターを使用するようにコード(operator =内)を変更することです。標準形は次のとおりです。

Vector2f temp = Vector2f(arg);
swap(*this, temp)   // You need to implement a swap method
return *this; 

(詳細については、ハーブサッターによる例外的なC ++を参照してください)

于 2010-01-28T08:49:15.373 に答える
1

2番目のケースでは、建設ではなく割り当てを実行しています。独自のバージョンのコピー代入演算子を定義していません。つまり、コンパイラーが独自のバージョンを提供します。コンパイラが提供するコピー代入演算子は、暗黙的に次のように宣言されます。

Vector2f& operator =(const Vector2f& rhs);

この演算子の唯一のパラメーターは、constへの参照型であることに注意してください。

あなたのコードでは、代入の右側にタイプの一時的な右辺値オブジェクトを提供することを主張しています。Vector2f

tempVector2 = Vector2f(0.0f, 0.0f);

これは、の参照パラメータがoperator =クラスタイプの一時的な右辺値で初期化されることを意味します。言語仕様(8.5.3 / 5)によると、コンパイラーは、実際に参照をアタッチする前に、その一時オブジェクトを必要な回数だけコピーすることができます。最終的には、コピーを停止し、最後にオペレーターを呼び出す必要があります。通常、コンパイラはコピーに夢中になることはありません(ほとんどのコンパイラはコピーをまったく行いません)が、あなたの場合、これが問題のようです。何らかの理由で、コンパイラは無限のコピーループにロックされ、停止することはありません。何が原因なのかわかりません。コンパイラのバグである可能性があります。

でも注意してください

tempVector2 = Vector2f(tempVector1);  

あなたはまだ一時的な右辺の形で右側を供給しています。Vector2f右辺値は、何らかの理由でそこに配置された明示的なキャストの結果です。なぜあなたがこれをしたのか分かりません。問題が実際にコンパイラーにある場合(そして、表示されていないコードにない場合)、

tempVector2 = tempVector1;  

割り当ては問題なく実行されます。これは、コンパイラのバグであることが判明した場合に、実際に問題を回避する方法です。コピーコンストラクタとコピー代入演算子の引数として一時的なものを使用するのをやめます。

于 2010-01-28T09:04:18.213 に答える
0

IDEで実行します。ループに入ったら、「一時停止」ボタンを押します。問題が何であるかが正確にわかります。これが理由です。

于 2010-02-19T17:52:11.623 に答える