2012-05-15 35 views
7

私は2つのローカルオブジェクトを持っているとします。関数が返ってきたら、最初にどのスコープから外れているか保証されていますか?例えばデストラクタの呼び出し順序とポイント

私はこのようなクラスを持っている:

class MutexLock 
{ 
    /* Automatic unlocking when MutexLock leaves a scope */ 
    public: 
     MutexLock (Mutex &m)  { M.lock(); } 
     ~MutexLock(Mutex &m)  { M.unlock(); } 
}; 

これはスコープの外に行くときに自動的にミューテックスを解放するために使用される非常に一般的なトリックです。しかし、2つのミューテックスが必要な場合はどうすればよいですか?

void *func(void *arg) 
{ 
    MutexLock m1; 
    MutexLock m2; 

    do_work(); 

} // m1 and m2 will get unlocked here. But in what order? m1 first or m2 first? 

これは本当にデッドロックを引き起こすことはできません。しかし、リソースを解放する順序がユーザーにとって有益な場合があります。その場合、デストラクタに頼るのではなく、明示的にすることが重要ですか?

また、どのような場合でもコンパイラによって破壊が遅延する可能性がありますか?私は何を意味することはデストラクタが建設の逆の順序で呼び出されます

func() 

{ 

    { 
     foo f(); 
    } ---------> Can compiler choose to not destroy f here, rather do it at the time when func() is returning. 
} 

答えて

10

// m1 and m2 will get unlocked here. But in what order? m1 first or m2 first?

です:その後、m2m1

その場合、デストラクタに頼るのではなく明示的にすることが重要ですか?

破壊の順序は、あなたがそれに頼ることができるように明確に規定されています。

また、コンパイラによってどのような場合でも破壊が遅延する可能性がありますか?

号それがなかった場合、それは(あなたのMutexLockクラスは、その非常に良い例です)RAIIベースのコードの多くを破ります。

+1

@ aixの回答の最初の部分をサポートするため、これは標準から抜粋したものです(ドラフト版、日付:2006-11-06 ---後のバージョンでは変更されていません)。 ): "スコープを終了すると(ただし達成された)、デストラクタは、そのスコープ内で宣言の逆の順序で宣言された自動保存期間(名前付きオブジェクトまたは一時的オブジェクト)を持つすべての構築済みオブジェクトに対して呼び出されます。もちろん、あなたの例には自動変数宣言が含まれています。 – sturmer

2

破壊は構造の逆順で行われます。最初はm2、次にm1です。

コンパイラは、オブジェクトの有効期限をスコープの終了(})の後にすることはできません。

0

オブジェクトはスコープ外になると常に破棄されます。これはjavaではありません。あなたが指示した場所で破壊され、funcの最後に破壊されることはありません。一般に、デストラクタは構築の順序と逆の順序で呼び出されます。

4

その場合、デストラクタに頼るのではなく明示的にすることが重要ですか?
いいえ、必須ではありません。
スコープ内のオブジェクトの破棄の順序はよく定義されています。
これは、作成された順序とはまったく反対です。


また、破壊はどのような場合には、コンパイラによって遅延することができますか?
No.
コンパイラは、その目的はありません。RAIIです。これは、暗黙的に&のリソースを解放するメカニズムを提供し、プログラマーの一部に対して明示的な手作業なしにリソースを割り当て解除します。
RAIIの目的と並行して破壊を遅らせる必要がある場合は、マニュアルリソース管理が必要です。
手動リソース管理が必要な場合は、newを介してヒープに割り当てられたポインターを持つことができ、それらが指すオブジェクトは、delete呼び出しと呼び出しの順番で明示的に割り当てを解除するまで有効です。
もちろん、そうすることもお勧めできません。

関連する問題