C ++コミュニティ内の知識豊富な著者によると、以下に示すコードはコンパイルしないでください。彼は間違っていますか?

StackOverflow https://stackoverflow.com/questions/8367459

質問

ハーブによると、以下のコードはコンパイルされません。このサイトを参照してください http://www.gotw.ca/gotw/066.htm 次のテキストを抽出したところから、 function-try-blocks :

いくつかの道徳に向かって

ちなみに、これはまた、コンストラクター関数 - トリブロックの唯一の(繰り返しのみ)使用できるのは、ベースまたはメンバーのサブオブジェクトからスローされた例外を変換することであることを意味します。それは道徳的な#1です。次に、モラル#2は、Destructor機能 - トリブロックは完全にuseleであると言います -

" - ちょっと待って!"部屋の真ん中から誰かが中断しているのが聞こえます。 「私は道徳的な#1に同意しません。コンストラクター機能 - トリブロックの別の使用可能な使用、つまり初期イザーリストまたはコンストラクターボディに割り当てられた無料のリソースを考えることができます!」

申し訳ありませんが、いや。結局のところ、コンストラクターTryBlockのハンドラーに入ると、コンストラクター本体のローカル変数もすでに範囲外であり、ベースサブオブジェクトやメンバーオブジェクトがもう存在しないことが保証されていることを忘れないでください。あなたは彼らの名前を参照することさえできません。オブジェクトの部分が構築されなかったか、構築されたものがすでに破壊されています。したがって、クラスのベースやメンバーに言及することに依存するものをクリーンアップすることはできません(とにかく、それはベースとメンバーのデストラクタの目的ですよね?)。

この引用を仮定すると、オブジェクトとして次のコードをコンパイルしないでください 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;
}
役に立ちましたか?

解決

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

ハンドラー内のオブジェクトの非静的なメンバーまたはベースクラスを参照すると、そのオブジェクトのコンストラクターまたはデストラクタの関数 - デストラクタの対象となります。 未定義の動作.

他のヒント

この引用を仮定すると、次のコードはコンパイルしてはなりません...

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

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top