1

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

3 に答える 3

2

Herb Sutter が実際にコンパイルできないと言っているとは思いません。彼は、標準が状況について述べなければならないことの結果を説明しているだけです(15.3.10):

そのオブジェクトのコンストラクタまたはデストラクタの function-try-block のハンドラーでオブジェクトの非静的メンバーまたは基本クラスを参照すると、未定義の動作が発生します。

于 2011-12-03T12:08:34.283 に答える
1

この引用を仮定すると、次のコードはコンパイルされないはずです...

まあ、彼はそれらが決してコンパイルされないとは言いませんでした。どちらかといえば、引用を「これを行うことは未定義」を意味すると解釈しました。未定義の動作は、コンパイルが成功したり、後で驚くべきことを行ったりすることを含め、あらゆる結果をもたらすことができます。

于 2011-12-03T12:06:17.463 に答える
0

コンパイラは異なります。また、コンパイラがコンパイルするコードをどの程度厳密にするかを決定するスイッチもあります。このコードは確かにエラー (セグメント障害など) を引き起こします。コンパイラのすべてのスイッチを有効にして、強制的にこれを検出するようにしてください。

于 2011-12-03T12:04:04.540 に答える