2
class Error1
{

public:

int errorcode;
Error1(int x):errorcode(x){ cout<<"CTOR Error1"<<endl; }
//Error1(Error1& obj ){
//    errorcode = obj.errorcode;
//    cout<<"CopyCTOR Error1"<<endl;
//}
~Error1(){cout<<"DTOR Error1"<<endl; }
};

void fun()
{
cout<<"Inside fun"<<endl;
throw(Error1(5));
}

int main()
{
try{

    fun();
}
catch(Error1& eobj)
{
    cout<<"Error1 type occured with code:"<<eobj.errorcode<<endl;
}
cin.get();

}

出力:

Inside fun

CTOR Error1

DTOR Error1

Error1 type occured with code:5

DTOR Error1

この出力は、Error1 オブジェクトが catch ハンドラー用にコピー構築されていることを示しています。Error1 オブジェクトにはコピー コンストラクタが定義されていないため、デフォルトのコピー コンストラクタが使用されます。

コピー コンストラクターを定義するためのコメント セクションのコメントを外すと、次の出力が得られます。

Inside fun

CTOR Error1

Error1 type occured with code:5

DTOR Error1

DTOR が 1 つしか呼び出されないのはなぜですか? 例外が参照によってキャッチされたとしても、一時的なものがまだ作成されていると思います。

4

2 に答える 2

1

どのコンパイラを使用していますか?

引数付きのコピー コンストラクターのバージョンを導入 (つまり、コメントを解除) するとError1& obj、コードが無効になるはずです。throw引数のコピーを作成できるはずですが、コピーコンストラクターのバージョンでは一時的なコピーが無効になっています。コードの形式が正しくありません。コンパイラがそれを受け入れる場合、おそらく非 const 参照を一時変数にバインドすることを違法に許可しているためです (拡張機能が有効になっている MSVC++ コンパイラであると思われます)。

元の実験は、想定/許可されているとおりに機能します。の引数はthrow、後でパラメーターを初期化するために使用される内部一時ファイルにコピーされcatchます。コンパイラは元のテンポラリを直接使用することが許可されていますが、それに応じてその寿命を延ばします。

于 2012-07-07T06:30:12.497 に答える
-1

他のエラーがあるかもしれませんが、私が今見ているのは、タイプthrow(Error1(5));の一時的な (またはrvalue)を作成することError1です。が必要ですlvalue。つまり、実行する必要がありますthrow(*new Error1(5));(メモリリークが発生すると思いますが、間違っている可能性があります)。または、グローバルError1オブジェクトを作成してそれをスローすることもできます。

PS:throw(*new Error1(5));誰かがコメントしたい場合は、メモリリークが発生するかどうかを知りたいです。catchキャッチしたオブジェクトを破壊しますか? もしそうなら、Error1必要なときにいつでも新しい を作成するだけで問題ないと思います。

于 2012-07-07T06:53:48.527 に答える