Herb Sutter によると、以下のコードはコンパイルできません。このサイトhttp://www.gotw.ca/gotw/066.htmを参照してください。ここから、次のテキストを抽出しましたfunction-try-blocks。
いくつかの道徳に向けて
ちなみに、これは、コンストラクター function-try-block の唯一の (繰り返しのみの) 可能な使用法が、ベースまたはメンバー サブオブジェクトからスローされた例外を変換することであることも意味します。それがモラル #1 です。次に、モラル #2 は、デストラクタ関数の try ブロックは完全に有用であると述べています。
" - ちょっと待って!" 部屋の真ん中から誰かが割り込むのが聞こえます。「モラル #1 には同意しません。コンストラクター関数の try ブロックの別の用途、つまり、イニシャライザー リストまたはコンストラクター本体で割り当てられたリソースを解放することを考えることができます!」
申し訳ありません。結局のところ、コンストラクターの try-block のハンドラーに入ると、コンストラクター本体のローカル変数も既にスコープ外であり、基本サブオブジェクトまたはメンバー オブジェクトが存在しないことが保証されていることを覚えておいてください。彼らの名前を参照することさえできません。オブジェクトの一部が構築されていないか、構築された部分が既に破棄されています。したがって、クラスのベースまたはメンバーへの参照に依存するものをクリーンアップすることはできません (とにかく、それがベースおよびメンバーのデストラクタの目的ですよね?)。
この引用符を仮定すると、プロセスが句catに実行されるまでにオブジェクトがすでに破棄されているため、次のコードはコンパイルされません。catchしかし、少なくとも VSC2008 ではそうです。
class Cat
{
public:
Cat() { cout << "Cat()" << endl; }
~Cat() { cout << "~Cat()" << endl; }
};
class Dog
{
public:
Dog() { cout << "Dog()" << endl; throw 1; }
~Dog() { cout << "~Dog()" << endl; }
};
class UseResources
{
class Cat *cat;
class Dog dog;
public:
UseResources();
~UseResources() { delete cat; cat = NULL; cout << "~UseResources()" << endl; }
};
UseResources::UseResources() try : cat(new Cat), dog() { cout << "UseResources()" << endl; } catch(...)
{
delete cat;
throw;
}